-2

I have designed a board that samples audio input using a 16 bit DAC at 48kHz. It stores the data as signed 16-bit integers. I have also implemented a 16 bit ADC on the board and I am able to pass audio through the board successfully.

I would like to design a low pass filter using MATLAB and implement it on this board. I understand how to create basic filters using MATLAB but I cant quite grasp how to bridge the gap between creating the filter in MATLAB and implementing this filter using C code on my board. I would like to be able to pass the signal into the board and observe the filtered signal on the output in 'real-time'.

How can this be achieved?

BBales
  • 6,588
  • 3
  • 16
  • 19
  • 1
    By writing c code that does that. You can't ask this!!! There are many many ways to do it. – Iharob Al Asimi Nov 24 '15 at 00:40
  • @iharob why don't you point me in the right direction and tell me one of the many ways that I could achieve this? – BBales Nov 24 '15 at 00:43
  • 2
    first, how is your matlab filter implemented? could you post the code you used? – Ryu Nov 24 '15 at 00:46
  • 1
    Also have you tried researching to see how other people have done it? https://kiritchatterjee.wordpress.com/2014/11/10/a-simple-digital-low-pass-filter-in-c/ – Fantastic Mr Fox Nov 24 '15 at 00:47
  • @Ryu I am able to create a simple filter with B and A coefficient vectors using something like butter(). I have also tried using the filter builder tool. When I use the filter builder tool I end up with a Matlab object, I'm not sure what to do with this object. – BBales Nov 24 '15 at 00:50
  • @Ben thanks for the link. I have looked around online, the link you provided touches on the creation of a single pole low pass filter. I understand that I can filter data using a difference equation with the coefficients from A and B generated in MATLAB, however, how do I know that this will work with the signed 16 bit data I am manipulating? The vectors generated in MATLAB have floating point values so I can't just put them in.. my next thought is that I can normalize these coefficients. My next concern is that I have a sampling frequency of 48kHz, does this change how I must specify cutoffs? – BBales Nov 24 '15 at 00:56
  • Because that is not what this site is for. – Iharob Al Asimi Nov 24 '15 at 02:03
  • So basically the question is how to implement butter in c? For this see also: http://stackoverflow.com/questions/10373184/bandpass-butterworth-filter-implementation-in-c The best questions for stackoverflow are small questions: either ask how these filters work or ask how to make a specific part of it in c or ask why the whole thing is not working (once you made it). This is probably just to broad for a single question. – NoDataDumpNoContribution Nov 25 '15 at 12:15

1 Answers1

1

ok, you said that you get your coefficients from a [B,A]= butter(..) likewise filter (try getting them in Z domain AKA digital filter), those A,B coefficients correspond to a simple transfer function you know

H(z) = B(z)/A(z) = (b(1)+b(2) z^−1+⋯+b(n+1) z^−n)/(a(1)+a(2) z^−1+⋯+a(n+1) z^−n)

right?

you just need to remember that the output y = H(z)*x or in other words

y = B(z)/A(z) * x and finally A(z)*y = b(z)*x

and what was x(t) * z^-1 equals? yep x(t-1)

that means that you'll end with an ecuation similar to:

y(t)*a(1)+y(t-1)*a(2)+⋯+y(t-n)a(n+1) = x(t)*b(1)+x(t-1)*b(2)+⋯+x(t-n)b(n+1)

and what we need is the actual value of y(t) with the known values of actual x(t) and past x(t-1) etc, and also with known and stored values of past y(t-1) etc...

y(t) = 1/a(1) * (x(t)*b(1)+x(t-1)*b(2)+⋯+x(t-n)b(n+1) - y(t-1)*a(2)-⋯-y(t-n)a(n+1))

that means you need two arrays for x and y, and apply the equation with the B and A arrays you got from matlab...

sadly, this assumes you ALREADY took in consideration the sampling time in the butter() (hence Wn should be normalized) and make sure you take your samples at that exact sampling time (and ideally calculate your output at the exact time too)

Ryu
  • 172
  • 6
  • So if I understand correctly, I can take these B and A coefficients and normalize them to be in signed 16 bit format, I can then just apply them using the difference equation on input and output, storing previous inputs and outputs as necessary to satisfy x(t-n) and y(t-n) etc? – BBales Nov 24 '15 at 01:25
  • 1
    right! but don't forget two things: you need to normalize the input, the coefficients and then the output, if your ADC spits a signed 16 bits for 1 Vpp you are lucky but most of the time you need to do that too. (same with the value you'll feed to the DAC) I suggest you to start with float values from -1.0 to 1.0 and after you get the idea, normalize to be able to use 16 or 32 bit fixed point math (with integers) – Ryu Nov 24 '15 at 01:37
  • 1
    uh oh, also don't forget, once you finish one iteration, update your arrays so x[0] goes to x[1] but x[1] goes to x[2], etc... in other words, 'multiply by z' everything (shift to past) – Ryu Nov 24 '15 at 01:39
  • 1
    and finally this is what is called a Infinite Response filter (IRF filter) because it uses past values of the output Y to calculate the new output... you can also search for a Finite Response Filter (FRF filter I think) which only uses past values of the input X (but it uses a lot of them)... maybe read about them... – Ryu Nov 24 '15 at 01:42
  • yes, I have conditioned the output of the DAC to be signed 16 bit format using C code. I planned on shifting the arrays after each iteration. From my understanding the IIR filter will be okay since a few future samples will only add a small bit of latency at 48kHz. – BBales Nov 24 '15 at 01:57