• 0
sgandhi

Audio processing

Question

I am working with nexys 4 ddr board...

I am using on board microphone and audio jack with task of giving audio at the mic and hearing through speakers or headphones at the jack.......

The nexys datasheet says there is a need of three signals... mic clk, lrsel and data output...

Now am I suppose to directly provide the name of the output pin in the xdc file in pwn audio section or there is some processing to be done?

the data output is H5 but where is it routed?... and on the other side audio jack needs pdm/ pwm input which is the same form that mic gives....so just help me with the logic...

 

THANK YOU 

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0

Hi, @muku!

If you look at the microphone data sheet found here, the LR clock is wired internally to ground.  Hence, you don't need to worry about it.  (This is very different from the traditional I2S audio interface)

To get the microphone input, start by setting the microphone clock to something between about 1MHz and 3MHz  (based on the datasheet).  You'll find the techniques here sufficient for that purpose.  You'll want to average the data to get it down from that clock rate down to something near 40-50kHz.  (44.1kHz and 48kHz are common audio rates)  You may find that cascading a couple of block averages is sufficient for this purpose, or you may wish to design a "proper" filter for this purpose.

As for transmitting on the output port, I think you'll find this approach works quite well.  (Test-bench presentation here.)

Let me caution you, though, against any feedback loops.  Spare your hearing--don't transmit and listen at the same time.  ;)

Dan

Share this post


Link to post
Share on other sites
  • 0
18 hours ago, D@n said:

Hi, @muku!

If you look at the microphone data sheet found here, the LR clock is wired internally to ground.  Hence, you don't need to worry about it.  (This is very different from the traditional I2S audio interface)

To get the microphone input, start by setting the microphone clock to something between about 1MHz and 3MHz  (based on the datasheet).  You'll find the techniques here sufficient for that purpose.  You'll want to average the data to get it down from that clock rate down to something near 40-50kHz.  (44.1kHz and 48kHz are common audio rates)  You may find that cascading a couple of block averages is sufficient for this purpose, or you may wish to design a "proper" filter for this purpose.

As for transmitting on the output port, I think you'll find this approach works quite well.  (Test-bench presentation here.)

Let me caution you, though, against any feedback loops.  Spare your hearing--don't transmit and listen at the same time.  ;)

Dan

yes if I use 48kHz, what does couple of block averages mean? How will I write a vhdl code for it? Because right now at this point I don't want to use the filters.....

thank you for the help sir, would be grateful if you could help me make this stuff work.

Share this post


Link to post
Share on other sites
  • 0

@muku,

A block average is just the sum of some number of incoming samples.  Set the "0" to be a "1", the "1" to be a "-1", and you'll get rid of the DC bias (you could also set the "0" to be a "-1" and leave the "1" alone--it's just not my preference).  Then just average N samples together.    When you get a new sample, repeat by averaging the new last N samples together.  (You get to choose the N--there's a whole science behind it.  2MHz/48kHz might be a good first choice.)  Since a single block average like that doesn't produce a decent stop-band rejection, you may wish to apply the block average over and over again.  (6x-8x is usually good enough)

I'm hoping to blog about how to do this, but I haven't managed to get to it (yet).  I've got my (Verilog) examples written ... they're just not presentable enough yet.  It's really quite easy, and the wikipedia page gives away most of the secrets.  Use a block RAM, and you are likely to find it even easier to do.  (There are some other tricks associated with the CIC filtering approach, but those aren't quite as simple.  I mean .... they're fairly simple to implement, just not as simple to understand.)

The problem with the (cascaded) block average filtering approach is that it will distort the passband of your signal (i.e. the sound you wish to collect and preserve).  (Whether or not you notice is another question ...)  The only way around that is to use a more generic FIR--possibly in combination with block averaging approach in order to clean up from the results of your (cascaded) block average implementation.

Remember the purpose in your filter: to get rid of any aliasing artifacts.  That should set your design's stop-band cutoff at about 20-22 kHz or so, and give you something to work towards.

Dan

Share this post


Link to post
Share on other sites
  • 0

Hi @muku,

We also have our User demo here that uses the mic and the audio jack in HDL. This project uses most of the components on the board so you would use this more as a reference. Also, It is all in VHDL. 

cheers,

Jon  

Share this post


Link to post
Share on other sites
  • 0
On 10/8/2017 at 11:05 PM, D@n said:

@muku,

A block average is just the sum of some number of incoming samples.  Set the "0" to be a "1", the "1" to be a "-1", and you'll get rid of the DC bias (you could also set the "0" to be a "-1" and leave the "1" alone--it's just not my preference).  Then just average N samples together.    When you get a new sample, repeat by averaging the new last N samples together.  (You get to choose the N--there's a whole science behind it.  2MHz/48kHz might be a good first choice.)  Since a single block average like that doesn't produce a decent stop-band rejection, you may wish to apply the block average over and over again.  (6x-8x is usually good enough)

I'm hoping to blog about how to do this, but I haven't managed to get to it (yet).  I've got my (Verilog) examples written ... they're just not presentable enough yet.  It's really quite easy, and the wikipedia page gives away most of the secrets.  Use a block RAM, and you are likely to find it even easier to do.  (There are some other tricks associated with the CIC filtering approach, but those aren't quite as simple.  I mean .... they're fairly simple to implement, just not as simple to understand.)

The problem with the (cascaded) block average filtering approach is that it will distort the passband of your signal (i.e. the sound you wish to collect and preserve).  (Whether or not you notice is another question ...)  The only way around that is to use a more generic FIR--possibly in combination with block averaging approach in order to clean up from the results of your (cascaded) block average implementation.

Remember the purpose in your filter: to get rid of any aliasing artifacts.  That should set your design's stop-band cutoff at about 20-22 kHz or so, and give you something to work towards.

Dan

thank you for the reply sir .......

Could you guide how can I make band pass filter that takes audio data and output as audio? I would like to know the vhdl approach for band pass filter because I want to use it in my project. 

Could be more of help if it is behavioral modelling..............................

Share this post


Link to post
Share on other sites
  • 0

@muku,

A bandpass filter?  Sure.  What band will be your passband?  What signals do you wish to filter out?  (I was expecting you to want to implement a lowpass filter)  Do you know if you want to implement an IIR or an FIR filterIIR filter's can be cheaper, but they can also distort the band of interest as well. (That may be why I personally don't have as much experience with them ..) If you want an FIR filter, you might find this site useful for generating the coefficients that you need.

Dan

Share this post


Link to post
Share on other sites
  • 0
5 hours ago, D@n said:

@muku,

A bandpass filter?  Sure.  What band will be your passband?  What signals do you wish to filter out?  (I was expecting you to want to implement a lowpass filter)  Do you know if you want to implement an IIR or an FIR filterIIR filter's can be cheaper, but they can also distort the band of interest as well. (That may be why I personally don't have as much experience with them ..) If you want an FIR filter, you might find this site useful for generating the coefficients that you need.

Dan

Yes band pass... The reason is I want to use three or four band pass filters , each of them will pass some respective frequency band (input being an audio range)... The  idea is to provide the facility of boasting or attenuating a particular band so I thought band pass would be the best option for that.......... I just want band pass filter not FIR one...........

Share this post


Link to post
Share on other sites
  • 0

There are three phases to this design.

Phase 1 -- get the mic input to work at all.

Phase 2 -- develop DSP algorithm for FPGA.

Phase 3 -- implement and test.

One thing you can try is getting the mic input into a file that you can use for testing DSP algorithms out.  It is better to test out DSP on a computer first as the iteration time is much lower.  You can also try DSP algorithms on voice recordings from the internet to get a basic idea of what processing might sound like.  Finally, implementation.  For this design, I suggest using a DSP48, a small RAM, and a small FSM.  FIR filters are nicer as the fixed-point models are predictable and fairly easy.  IIR filters are probably more applicable, but fixed point models could have more issues.  In either case though, you are looking at generating coefficients in matlab/octave or something like that.

Share this post


Link to post
Share on other sites
  • 0

Thanks Dan .......

 

@D@n

Now I am using a FIR bandpass filter with input vector of 16 bit and output vector of 16 bit but my number of taps exceed 400 !!!!!

Could you help me out ...

 

Regards,

Muku

 

 

 

Share this post


Link to post
Share on other sites
  • 0

@muku,

400 taps sounds quite reasonable.  You are running on a 100MHz clock, right?  That should allow you to time-slice (100MHz/48kHz ~=) 2082 multiplies or so into a single DSP element, much more than 400.  You might even manage to do five separate 400 tap filters with only a single DSP element.  Gosh, if you got a little creative, and if all of your filters were symmetric, you might even manage to drop your multiply count down to 200 multiplies per filter (one multiply for two coefficients) and then share ten filters across one hardware multiply (DSP) element.

Your basic algorithm will 1) wait for a new sample, 2) write that sample to memory, 3) loop through memory: reading one element from memory and one element from a second memory containing your filter coefficients, 4) multiply the output of that memory value by the filter coefficient, 5) accumulate the results of the multiplies into one sum, and finally 6) produce an output when done.  (Don't use the VHDL "for" loop--you'll end up doing all of this in one clock.)  This basic algorithm would need to be adjusted to make it apply to multiple filters at once (should you wish to do so), but even that is quite doable. 

Others have solved the symmetric filter approach--I'm still scratching my head on how to do it.  My current thought is that if you are implementing a symmetric filter and want to exploit that symmetry, that you can move one sample from one memory to a second memory once it gets halfway through your delay line.  Then your memory read above would read one data element from each of two memories, you'd then add the two data elements together and then do the single multiply.  It's a little harder, but still a good exercise for a student.  (I'd do the approach outlined above before trying this one.)

There are other signal processing approaches, should you be interested.  For example 1) you might wish to look up what a Fourier transform filter bank is.  If built properly, you can apply a polyphase filter to your signal and then FFT it. (3-6 taps will be sufficient here)  You can then multiply each band in the output of the FFT by your favorite scale factor--one scale per FFT bin, and then use an IFFT and another polyphase filter (3-6 taps again) to reconstruct your results.  2) A simpler approach might be to just filter and downsample in one step, and then filter and upsample going back up.  I've only done this simpler approach in software however--where it is very effective.  I haven't yet figured out how to do it in HDL.

While these are other valid approaches, I'd recommend sticking with the earlier approaches--especially since you only have 400 taps to implement in 2082 clocks.

Oh, one more item, be aware of truncation effects.  That 400 tap filter in floating point may not produce the same quality of output once you rebuild it into 16-bit samples.

Dan

Share this post


Link to post
Share on other sites
  • 0

@muku,

I'm not sure.  I'm further puzzled by the fact that the internal coefficients have a width associated with them that really *cannot* be controlled by any generic parameter.

I know that in Verilog, I'd capture the width of the filter coefficient with a constant defined in the same context that the coefficients themselves are defined in.

Perhaps if I understood VHDL better I might have more of an opinion on the matter.  Perhaps @Piasa might have an insight?

Dan

Share this post


Link to post
Share on other sites
  • 0

It isn't ideal.  This is a common case of half-generalizing code.  The declared type for coefficients is generic but then restricted to a specific width in practice. 

My guess is that the original design had known sizes for coefs/inputs but also made them generics for "good practice".  Many practical designs are never tested outside of the original use case.

That the filter clearly uses signed values as "std_logic_vector" is also concerning.  Also, the values seem to be scaled in a sub-optimal manner -- none are close to max magnitude.  Like someone assumed intermediate stages had to have the same bit width as the output and also didn't know that FPGAs have had 18 bit multiplies for over a decade.

In both Verilog and VHDL the coefs should either be loaded from a file or be dynamically loaded after the fpga is programmed.

 

(also, this is clearly a symmetric FIR filter where someone also had a copy-paste error to make it asymmetric and then also not use an optimal implementation.  This is also probably not ideal for audio as attack/decay is possibly a concern over timeless spectrum.)

 

--edit:  This comment might have been harsh.  It might be that the original poster is also the person I criticized here.  In that case I would have been critical of the person asking for help from the community.  That was not my intent as my post was intended to help that person in solving their issues.

Edited by Piasa
head isn't tail

Share this post


Link to post
Share on other sites
  • 0

Thanks @Piasa .......

@Dan

One another query, currently I am using on board mic for nexys board to get my audio output through jack!!

Can I use the pen-drive slot to store some data stuff and than hear it through jack???

Any advantages of using on board mic that outweighs hearing the stored data?

And if it is so, where the data from some pen-drive or anything gets stored ?

Thank you.

 

Edited by muku

Share this post


Link to post
Share on other sites
  • 0

@muku,

Yes, you can use the FIR compiler to build a bandpass filter.

As regards to your pen-drive question, you might have better luck using an SD-card.  The USB ports on most of Digilent's boards can *only* be used with mice or keyboards.  (I think the Genesys board has an actual USB data  capability, but I can't remember.)

Dan

Share this post


Link to post
Share on other sites
  • 0

@muku,

At this point, I cannot answer.

  1. You'll need to do your own work
  2. I don't do VHDL

May I recommend you look at any examples Xilinx provides of how to use their IP?  Or, if not that, then at least look at the VHDL stub their wizard creates in order to know how to hook it up.

Dan

Share this post


Link to post
Share on other sites
  • 0

@D@n

Thanks for reply sir......

The data output from mic is the serial data so FIR compiler accepts serial or parallel data and the output of FIR is serial/parallel ???

Share this post


Link to post
Share on other sites
  • 0

@muku,

My guess is that you want a serial output.  Looking over the data sheet, though, it looks like you might use a parallel output structure to do all four of your bandpass filters at once, but ... I'd wait until I had one filter running in serial in and serial out before I started worrying about any parallel output structure(s).

Dan

Share this post


Link to post
Share on other sites
  • 0

Another doubt is my input is 16 bits and coefficient width is 8/16 bits but I require output as 16 bits !!!

Would it be feasible to truncate the output ( option provided during customizing the IP) ???

@D@n

Edited by muku

Share this post


Link to post
Share on other sites
  • 0

@muku

Yes, you can just drop the lower bits of a number.  There are consequences, however, when you are working with DSP.  You can find a bit of a discussion of how to do so without consequences (i.e. without bias) here.

Dan

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now