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

filtering introduces small DC offset #54

Open
superbigio opened this issue Nov 13, 2019 · 3 comments
Open

filtering introduces small DC offset #54

superbigio opened this issue Nov 13, 2019 · 3 comments

Comments

@superbigio
Copy link

I have noticed that for every value except rise_time = 0, the filtering process introduces a small DC offset in the LTC square wave making the wave no longer being centered around zero. I haven't delved into it to understand why it happens and in my system this doesn't affect the readability of the encoded signal so everything still works. However I was wondering if it's something that is possible to fix.

@x42
Copy link
Owner

x42 commented Nov 13, 2019

Likely because the LPF uses 8bit integer. Changing val to be a float probably fixes this.

libltc/src/encoder.c

Lines 54 to 58 in 84295cb

ltcsnd_sample_t val = SAMPLE_CENTER;
int m = (n+1)>>1;
for (i = 0 ; i < m ; i++) {
val = val + tcf * (tgtval - val);
wave[n-i-1] = wave[i] = val;

@superbigio
Copy link
Author

superbigio commented Nov 13, 2019

Actually val gets promoted to double already because of the tcf variable. So both the multiplication and accumulation of the filter get evaluated in double precision. However the result gets truncated to 8 bits when assigned back to val. I tested it and found out that rounding instead of truncating would be enough to solve the issue.

ltcsnd_sample_t val = SAMPLE_CENTER; 
 int m = (n+1)>>1; 
 for (i = 0 ; i < m ; i++) { 
 	val = lround(val + tcf * (tgtval - val)); 
 	wave[n-i-1] = wave[i] = val;

@x42
Copy link
Owner

x42 commented Nov 13, 2019

Nice!

It should probably use float. double precision is overkill here.
Also I'm not sure if lround() is portable. src/ltc.c defines a rint() for MSVC and AVR. This might need a similar workaround.

eg.

val = floorf (.5f + val + tcf * (tgtval - val)); 

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