Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: Can't apply the needed filtering without introducing a lot of digital noise #40

Open
TooDissing opened this issue May 31, 2022 · 11 comments

Comments

@TooDissing
Copy link
Contributor

TooDissing commented May 31, 2022

Hey,

When adding additional filters or when tuning the EQ up to +12, then I hear pretty bad digital noise. It sounds like clipping, but could also be something else.
Not sure how and where to test for this?

I also tried reducing the signal by 50% by multiplying with 0.5. But the digital artifacts still persisted. So it most be somewhere else in the chain.

@feelfreelinux
Copy link
Member

If i understand correctly, the issue most likely related to lack of headroom in the EQ code. You could try to lower the value in SoftwareVolumeProcessor.cpp (default volume to something lower) in order to simulate it, but its not really the best solution.

@TooDissing
Copy link
Contributor Author

was looking at that code. Does the µVox driver override this code?

std::vector<uint8_t> volumeLookup = std::vector<uint8_t>(
        {255, 160, 120, 100, 90, 85, 80, 75, 70, 65, 61, 57, 53, 50, 47, 44, 41,
         38,  35,  32,  29,  26, 23, 20, 17, 14, 12, 10, 8,  6,  4,  2,  0});

Because when running higher than 24 we are adding gain.

@TooDissing
Copy link
Contributor Author

Oh, and this artifacts seems to be there with even very low volume.

Are we touches gain somewhere else in the platform?

With this recent test I am doing a high pass shelf with negative gain. This should really not introduce clipping

@TooDissing
Copy link
Contributor Author

TooDissing commented May 31, 2022

are the processor out of juice? And any good way to verify this?

@TooDissing
Copy link
Contributor Author

Assuming the problem is missing EQ headroom, is there any way I can validate whether or not we are close to the limit?
What are the maximum allowed value for the elements in the data_16 array? Then I could start there.

It enters as uint8_t but is then cast to int16_t.
With Spotify I assume we are talking a 16 signal.

Been using Camila DSP with the same set of filters and there it is working pretty good.

Any idea on when and where this is converted to a 32bit one (if at all)?

Any other great ideas of where to look?

@TooDissing
Copy link
Contributor Author

I am a bit lost here. Tried looking at various classes, but didn't find any smoking gun.
Did a small "data capture" of the data being processed by the filters (in EqualizerProcessor.h). How ever this data doesn't tell us much if we do not know what the limit is.

So any clue on the maximum value?

Data coming in:

I [eq] EqualizerProcessor.h:155: process; data_16[0] (d): -653
I [eq] EqualizerProcessor.h:156: process; data_16[0] (d): -1931
I [eq] EqualizerProcessor.h:157: process; dataLeft[0]: -0.01992858760058879852
I [eq] EqualizerProcessor.h:158: process; dataRight[0]: -0.05893124267458915710
I [eq] EqualizerProcessor.h:155: process; data_16[100] (d): -3974
I [eq] EqualizerProcessor.h:156: process; data_16[100] (d): -4110
I [eq] EqualizerProcessor.h:157: process; dataLeft[100]: -0.12128055840730667114
I [eq] EqualizerProcessor.h:158: process; dataRight[100]: -0.12543107569217681885
I [eq] EqualizerProcessor.h:155: process; data_16[200] (d): -3728
I [eq] EqualizerProcessor.h:156: process; data_16[200] (d): -3629
I [eq] EqualizerProcessor.h:157: process; dataLeft[200]: -0.11377300322055816650
I [eq] EqualizerProcessor.h:158: process; dataRight[200]: -0.11075167357921600342
I [eq] EqualizerProcessor.h:155: process; data_16[300] (d): -3300
I [eq] EqualizerProcessor.h:156: process; data_16[300] (d): -3868
I [eq] EqualizerProcessor.h:157: process; dataLeft[300]: -0.10071108490228652954
I [eq] EqualizerProcessor.h:158: process; dataRight[300]: -0.11804559826850891113
I [eq] EqualizerProcessor.h:155: process; data_16[400] (d): 133
I [eq] EqualizerProcessor.h:156: process; data_16[400] (d): -819
I [eq] EqualizerProcessor.h:157: process; dataLeft[400]: 0.00405896175652742386
I [eq] EqualizerProcessor.h:158: process; dataRight[400]: -0.02499466016888618469
I [eq] EqualizerProcessor.h:155: process; data_16[500] (d): 4946
I [eq] EqualizerProcessor.h:156: process; data_16[500] (d): 5215
I [eq] EqualizerProcessor.h:157: process; dataLeft[500]: 0.15094454586505889893
I [eq] EqualizerProcessor.h:158: process; dataRight[500]: 0.15915402770042419434
I [eq] EqualizerProcessor.h:155: process; data_16[600] (d): 2968
I [eq] EqualizerProcessor.h:156: process; data_16[600] (d): 2819
I [eq] EqualizerProcessor.h:157: process; dataLeft[600]: 0.09057893604040145874
I [eq] EqualizerProcessor.h:158: process; dataRight[600]: 0.08603167533874511719
I [eq] EqualizerProcessor.h:155: process; data_16[700] (d): -1605
I [eq] EqualizerProcessor.h:156: process; data_16[700] (d): -682
I [eq] EqualizerProcessor.h:157: process; dataLeft[700]: -0.04898220673203468323
I [eq] EqualizerProcessor.h:158: process; dataRight[700]: -0.02081362344324588776
I [eq] EqualizerProcessor.h:155: process; data_16[800] (d): 103
I [eq] EqualizerProcessor.h:156: process; data_16[800] (d): -1696
I [eq] EqualizerProcessor.h:157: process; dataLeft[800]: 0.00314340647310018539
I [eq] EqualizerProcessor.h:158: process; dataRight[800]: -0.05175939202308654785
I [eq] EqualizerProcessor.h:155: process; data_16[900] (d): 2026
I [eq] EqualizerProcessor.h:156: process; data_16[900] (d): 1013
I [eq] EqualizerProcessor.h:157: process; dataLeft[900]: 0.06183050200343132019
I [eq] EqualizerProcessor.h:158: process; dataRight[900]: 0.03091525100171566010
I [eq] EqualizerProcessor.h:155: process; data_16[1000] (d): 1460
I [eq] EqualizerProcessor.h:156: process; data_16[1000] (d): 787
I [eq] EqualizerProcessor.h:157: process; dataLeft[1000]: 0.04455702379345893860
I [eq] EqualizerProcessor.h:158: process; dataRight[1000]: 0.02401806786656379700

Data coming out:

I [eq] EqualizerProcessor.h:230: processed; data_16[0] (d): -219
I [eq] EqualizerProcessor.h:231: processed; data_16[0] (d): -366
I [eq] EqualizerProcessor.h:232: processed; dataLeft[0]: -0.006712
I [eq] EqualizerProcessor.h:233: processed; dataRight[0]: -0.011195
I [eq] EqualizerProcessor.h:230: processed; data_16[100] (d): -2798
I [eq] EqualizerProcessor.h:231: processed; data_16[100] (d): -2824
I [eq] EqualizerProcessor.h:232: processed; dataLeft[100]: -0.085407
I [eq] EqualizerProcessor.h:233: processed; dataRight[100]: -0.086193
I [eq] EqualizerProcessor.h:230: processed; data_16[200] (d): -3145
I [eq] EqualizerProcessor.h:231: processed; data_16[200] (d): -3433
I [eq] EqualizerProcessor.h:232: processed; dataLeft[200]: -0.095996
I [eq] EqualizerProcessor.h:233: processed; dataRight[200]: -0.104772
I [eq] EqualizerProcessor.h:230: processed; data_16[300] (d): -2544
I [eq] EqualizerProcessor.h:231: processed; data_16[300] (d): -2968
I [eq] EqualizerProcessor.h:232: processed; dataLeft[300]: -0.077643
I [eq] EqualizerProcessor.h:233: processed; dataRight[300]: -0.090594
I [eq] EqualizerProcessor.h:230: processed; data_16[400] (d): -1194
I [eq] EqualizerProcessor.h:231: processed; data_16[400] (d): -1360
I [eq] EqualizerProcessor.h:232: processed; dataLeft[400]: -0.036443
I [eq] EqualizerProcessor.h:233: processed; dataRight[400]: -0.041511
I [eq] EqualizerProcessor.h:230: processed; data_16[500] (d): 1863
I [eq] EqualizerProcessor.h:231: processed; data_16[500] (d): 1892
I [eq] EqualizerProcessor.h:232: processed; dataLeft[500]: 0.056879
I [eq] EqualizerProcessor.h:233: processed; dataRight[500]: 0.057752
I [eq] EqualizerProcessor.h:230: processed; data_16[600] (d): 2875
I [eq] EqualizerProcessor.h:231: processed; data_16[600] (d): 2863
I [eq] EqualizerProcessor.h:232: processed; dataLeft[600]: 0.087742
I [eq] EqualizerProcessor.h:233: processed; dataRight[600]: 0.087404
I [eq] EqualizerProcessor.h:230: processed; data_16[700] (d): 1789
I [eq] EqualizerProcessor.h:231: processed; data_16[700] (d): 1925
I [eq] EqualizerProcessor.h:232: processed; dataLeft[700]: 0.054617
I [eq] EqualizerProcessor.h:233: processed; dataRight[700]: 0.058761
I [eq] EqualizerProcessor.h:230: processed; data_16[800] (d): 1312
I [eq] EqualizerProcessor.h:231: processed; data_16[800] (d): 1004
I [eq] EqualizerProcessor.h:232: processed; dataLeft[800]: 0.040055
I [eq] EqualizerProcessor.h:233: processed; dataRight[800]: 0.030647
I [eq] EqualizerProcessor.h:230: processed; data_16[900] (d): 880
I [eq] EqualizerProcessor.h:231: processed; data_16[900] (d): 755
I [eq] EqualizerProcessor.h:232: processed; dataLeft[900]: 0.026875
I [eq] EqualizerProcessor.h:233: processed; dataRight[900]: 0.023065
I [eq] EqualizerProcessor.h:230: processed; data_16[1000] (d): 21
I [eq] EqualizerProcessor.h:231: processed; data_16[1000] (d): 305
I [eq] EqualizerProcessor.h:232: processed; dataLeft[1000]: 0.000668
I [eq] EqualizerProcessor.h:233: processed; dataRight[1000]: 0.009326

@feelfreelinux
Copy link
Member

I am a bit lost here. Tried looking at various classes, but didn't find any smoking gun. Did a small "data capture" of the data being processed by the filters (in EqualizerProcessor.h). How ever this data doesn't tell us much if we do not know what the limit is.

So any clue on the maximum value?

Data coming in:

I [eq] EqualizerProcessor.h:155: process; data_16[0] (d): -653
I [eq] EqualizerProcessor.h:156: process; data_16[0] (d): -1931
I [eq] EqualizerProcessor.h:157: process; dataLeft[0]: -0.01992858760058879852
I [eq] EqualizerProcessor.h:158: process; dataRight[0]: -0.05893124267458915710
I [eq] EqualizerProcessor.h:155: process; data_16[100] (d): -3974
I [eq] EqualizerProcessor.h:156: process; data_16[100] (d): -4110
I [eq] EqualizerProcessor.h:157: process; dataLeft[100]: -0.12128055840730667114
I [eq] EqualizerProcessor.h:158: process; dataRight[100]: -0.12543107569217681885
I [eq] EqualizerProcessor.h:155: process; data_16[200] (d): -3728
I [eq] EqualizerProcessor.h:156: process; data_16[200] (d): -3629
I [eq] EqualizerProcessor.h:157: process; dataLeft[200]: -0.11377300322055816650
I [eq] EqualizerProcessor.h:158: process; dataRight[200]: -0.11075167357921600342
I [eq] EqualizerProcessor.h:155: process; data_16[300] (d): -3300
I [eq] EqualizerProcessor.h:156: process; data_16[300] (d): -3868
I [eq] EqualizerProcessor.h:157: process; dataLeft[300]: -0.10071108490228652954
I [eq] EqualizerProcessor.h:158: process; dataRight[300]: -0.11804559826850891113
I [eq] EqualizerProcessor.h:155: process; data_16[400] (d): 133
I [eq] EqualizerProcessor.h:156: process; data_16[400] (d): -819
I [eq] EqualizerProcessor.h:157: process; dataLeft[400]: 0.00405896175652742386
I [eq] EqualizerProcessor.h:158: process; dataRight[400]: -0.02499466016888618469
I [eq] EqualizerProcessor.h:155: process; data_16[500] (d): 4946
I [eq] EqualizerProcessor.h:156: process; data_16[500] (d): 5215
I [eq] EqualizerProcessor.h:157: process; dataLeft[500]: 0.15094454586505889893
I [eq] EqualizerProcessor.h:158: process; dataRight[500]: 0.15915402770042419434
I [eq] EqualizerProcessor.h:155: process; data_16[600] (d): 2968
I [eq] EqualizerProcessor.h:156: process; data_16[600] (d): 2819
I [eq] EqualizerProcessor.h:157: process; dataLeft[600]: 0.09057893604040145874
I [eq] EqualizerProcessor.h:158: process; dataRight[600]: 0.08603167533874511719
I [eq] EqualizerProcessor.h:155: process; data_16[700] (d): -1605
I [eq] EqualizerProcessor.h:156: process; data_16[700] (d): -682
I [eq] EqualizerProcessor.h:157: process; dataLeft[700]: -0.04898220673203468323
I [eq] EqualizerProcessor.h:158: process; dataRight[700]: -0.02081362344324588776
I [eq] EqualizerProcessor.h:155: process; data_16[800] (d): 103
I [eq] EqualizerProcessor.h:156: process; data_16[800] (d): -1696
I [eq] EqualizerProcessor.h:157: process; dataLeft[800]: 0.00314340647310018539
I [eq] EqualizerProcessor.h:158: process; dataRight[800]: -0.05175939202308654785
I [eq] EqualizerProcessor.h:155: process; data_16[900] (d): 2026
I [eq] EqualizerProcessor.h:156: process; data_16[900] (d): 1013
I [eq] EqualizerProcessor.h:157: process; dataLeft[900]: 0.06183050200343132019
I [eq] EqualizerProcessor.h:158: process; dataRight[900]: 0.03091525100171566010
I [eq] EqualizerProcessor.h:155: process; data_16[1000] (d): 1460
I [eq] EqualizerProcessor.h:156: process; data_16[1000] (d): 787
I [eq] EqualizerProcessor.h:157: process; dataLeft[1000]: 0.04455702379345893860
I [eq] EqualizerProcessor.h:158: process; dataRight[1000]: 0.02401806786656379700

Data coming out:

I [eq] EqualizerProcessor.h:230: processed; data_16[0] (d): -219
I [eq] EqualizerProcessor.h:231: processed; data_16[0] (d): -366
I [eq] EqualizerProcessor.h:232: processed; dataLeft[0]: -0.006712
I [eq] EqualizerProcessor.h:233: processed; dataRight[0]: -0.011195
I [eq] EqualizerProcessor.h:230: processed; data_16[100] (d): -2798
I [eq] EqualizerProcessor.h:231: processed; data_16[100] (d): -2824
I [eq] EqualizerProcessor.h:232: processed; dataLeft[100]: -0.085407
I [eq] EqualizerProcessor.h:233: processed; dataRight[100]: -0.086193
I [eq] EqualizerProcessor.h:230: processed; data_16[200] (d): -3145
I [eq] EqualizerProcessor.h:231: processed; data_16[200] (d): -3433
I [eq] EqualizerProcessor.h:232: processed; dataLeft[200]: -0.095996
I [eq] EqualizerProcessor.h:233: processed; dataRight[200]: -0.104772
I [eq] EqualizerProcessor.h:230: processed; data_16[300] (d): -2544
I [eq] EqualizerProcessor.h:231: processed; data_16[300] (d): -2968
I [eq] EqualizerProcessor.h:232: processed; dataLeft[300]: -0.077643
I [eq] EqualizerProcessor.h:233: processed; dataRight[300]: -0.090594
I [eq] EqualizerProcessor.h:230: processed; data_16[400] (d): -1194
I [eq] EqualizerProcessor.h:231: processed; data_16[400] (d): -1360
I [eq] EqualizerProcessor.h:232: processed; dataLeft[400]: -0.036443
I [eq] EqualizerProcessor.h:233: processed; dataRight[400]: -0.041511
I [eq] EqualizerProcessor.h:230: processed; data_16[500] (d): 1863
I [eq] EqualizerProcessor.h:231: processed; data_16[500] (d): 1892
I [eq] EqualizerProcessor.h:232: processed; dataLeft[500]: 0.056879
I [eq] EqualizerProcessor.h:233: processed; dataRight[500]: 0.057752
I [eq] EqualizerProcessor.h:230: processed; data_16[600] (d): 2875
I [eq] EqualizerProcessor.h:231: processed; data_16[600] (d): 2863
I [eq] EqualizerProcessor.h:232: processed; dataLeft[600]: 0.087742
I [eq] EqualizerProcessor.h:233: processed; dataRight[600]: 0.087404
I [eq] EqualizerProcessor.h:230: processed; data_16[700] (d): 1789
I [eq] EqualizerProcessor.h:231: processed; data_16[700] (d): 1925
I [eq] EqualizerProcessor.h:232: processed; dataLeft[700]: 0.054617
I [eq] EqualizerProcessor.h:233: processed; dataRight[700]: 0.058761
I [eq] EqualizerProcessor.h:230: processed; data_16[800] (d): 1312
I [eq] EqualizerProcessor.h:231: processed; data_16[800] (d): 1004
I [eq] EqualizerProcessor.h:232: processed; dataLeft[800]: 0.040055
I [eq] EqualizerProcessor.h:233: processed; dataRight[800]: 0.030647
I [eq] EqualizerProcessor.h:230: processed; data_16[900] (d): 880
I [eq] EqualizerProcessor.h:231: processed; data_16[900] (d): 755
I [eq] EqualizerProcessor.h:232: processed; dataLeft[900]: 0.026875
I [eq] EqualizerProcessor.h:233: processed; dataRight[900]: 0.023065
I [eq] EqualizerProcessor.h:230: processed; data_16[1000] (d): 21
I [eq] EqualizerProcessor.h:231: processed; data_16[1000] (d): 305
I [eq] EqualizerProcessor.h:232: processed; dataLeft[1000]: 0.000668
I [eq] EqualizerProcessor.h:233: processed; dataRight[1000]: 0.009326

Hi! Could you send me a list of different filters you are using? I would like to test it out on my setup and debug :)

@TooDissing
Copy link
Contributor Author

Hi! Could you send me a list of different filters you are using? I would like to test it out on my setup and debug :)

Sure thing. The list is long, but basically having problems with the default setup as well.
The above is with a single filter: hsNegative1->generateNativeHighShelfCoEffs(100, -10.0, Q_FACTOR);.

But here's the entire list of filters needed as it is represented by the Camilla DSP YAML format: https://github.com/LydByDissing/stroem/blob/main/voicing/voicing-dsp-filters-descent.yaml

@TooDissing
Copy link
Contributor Author

BTW, any reason why the coefficient helper functions, in the ESP DSP Library, isn't used in this project?
https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#iir

Based on the benchmark documentation of dsps_biquad_f32_ae32(input, input, numSamples, coeffs, w);, each IIR filter takes 17450 CPU cycles to compute (dsps_biquad_f32 - biquad filter for 1024 input samples).
With 240Mhz, and if my math is correct, we should have plenty of bandwidth to process several filters.

@feelfreelinux
Copy link
Member

BTW, any reason why the coefficient helper functions, in the ESP DSP Library, isn't used in this project? https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#iir

Based on the benchmark documentation of dsps_biquad_f32_ae32(input, input, numSamples, coeffs, w);, each IIR filter takes 17450 CPU cycles to compute (dsps_biquad_f32 - biquad filter for 1024 input samples). With 240Mhz, and if my math is correct, we should have plenty of bandwidth to process several filters.

As for Euphonium being software targetted for multiple different architectures, I did not use esp-dsp directly. However, on ESP32 platform it does actually back up to using an assembly optimized biquad_f32_ae32 https://github.com/feelfreelinux/bell/blob/master/src/asm/biquad_f32_ae32.S - see here. It is basically the same version as espressif uses. That's why I do not think the issue is due to performance.

@TooDissing
Copy link
Contributor Author

BTW, any reason why the coefficient helper functions, in the ESP DSP Library, isn't used in this project? https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#iir
Based on the benchmark documentation of dsps_biquad_f32_ae32(input, input, numSamples, coeffs, w);, each IIR filter takes 17450 CPU cycles to compute (dsps_biquad_f32 - biquad filter for 1024 input samples). With 240Mhz, and if my math is correct, we should have plenty of bandwidth to process several filters.

As for Euphonium being software targetted for multiple different architectures, I did not use esp-dsp directly. However, on ESP32 platform it does actually back up to using an assembly optimized biquad_f32_ae32 https://github.com/feelfreelinux/bell/blob/master/src/asm/biquad_f32_ae32.S - see here. It is basically the same version as espressif uses. That's why I do not think the issue is due to performance.

Makes sense. Yes I saw that you are using the ASM implementation. My comment was mainly on the calculations of the filter coefficients. But as this will need to be used for multi platforms it makes sense, not to depend on that library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants