Arbitrary Sampling Rate Converter in VHDL

From Hackerspace ACKspace
Revision as of 21:29, 10 March 2014 by Danny Witberg (talk | contribs) (Serializing an IIR filter)
Jump to: navigation, search
Project: Arbitrary Sampling Rate Converter in VHDL
Featured:
State Active
Members Danny Witberg
GitHub No GitHub project defined. Add your project here.
Description ASRC's: What, how, why?
Picture
No project picture! Fill in form Picture or Upload a jpeg here

Summary

This project describes the theory of an Arbitrary Sampling Rate Converter, and a practical lightweight implementation in VHDL. ASRC's are often used in digital audio, to adapt an input to an output which differ in sampling rates to each other. If sampling rates are not matched, clicking noises and distortion can be heard and it could ruin your audio signal.

ASRC1.png

Hardware solutions

Standalone hardware SRC IC's for converting digital audio exist, but they are not cheap. To name some:

  • Analog Devices AD1895, AD1896 and AD1893
  • Cirrus Logic CS8420, CS8421, and CS8422
  • Texas Instruments SRC4190, SRC4382, SRC4392, SRC4190, SRC4184, SRC4194, SRC4190, SRC4192 and SRC4193
  • AKM AK4120, AK4121, AK4122, AK4127, AK4128 and AK4129

Theory of operation

Conversion between sampling rates of a digital (audio) signal is all about interpolation. Between the actual input signal and the desired output signal, additional samples must be created, or omitted. There are a number of techniques that can be used for this, but the most effective is to convert or "upsample" the input signal to a very high sampling rate, and then resample that signal to the desired output sampling rate. There are several ways to upsample a signal:

  • Copy input samples
  • Linear interpolation
  • Sinc function interpolation

ASRC2.png

The wrong way of upsampling: Copy samples

If you want a higher sampling rate, the easiest way to do this is to resample the input signal at a higher rate, thus creating copies of input samples. However, is is not the way to properly do this, because the interpolated samples do not differ from the actual input samples, and thus not improving any clicking noise and distortion. The output signal will sound just as bad, if not worse, than no conversion at all. Some other manipulation of the signal must be applied to improve quality.

ASRC3.png

The wrong way of upsampling: Linear interpolation

With a linear interpolation, you look at two consecutive input samples. Take the number of intermediate samples you want between these two, and gradually change the output value from one to the next sample. Although this can easily be implemented, this is not a good way to interpolate. This is because the original signal is very unlikely to change in a linear fashion, and if you interpolate like this, you introduce a distortion into the output signal. It is better than the copy sample method, but not usable for digital audio.

ASRC4.png

The right way of upsampling: Sinc function

A sinc function with the function of a low pass filter is the right way to go for digital audio applications. You start off with the least desirable option of upsampling: copy original samples into the new signal. This creates a frequency of 0 between those copied samples, because the signal does not change basically. But when a new original sample presents itself, a very high frequency is introduced, because the output value suddenly changes into the value of the original sample. This very high frequency is much higher than the maximum frequency of the original signal. If we filter out this very high frequency, the output signal rids itself from that sudden change in value, therefore must change slowly over time. This is exactly what we need! There are several ways to implement a low pass filter, but they can generally be divided into two categories: a Finite Impulse Response (FIR) filter and an Infinite Impulse Response (IIR) filter.

ASRC5.png

Filters: FIR filter

The way a FIR filter works is to multiply a input signal with another filter signal. The shape of the filter signal is called the filter kernel, and it determines the response of the FIR filter. You can have kernels for a low pass, high pass, band pass , band stop, or any other response you desire. How easy is it to load up a FIR filter function with a low pass filter kernel, and off we go! But unfortunately, there are some downsides to the FIR filter that we really can not use in our application. Because the whole kernel must be applied to the input signal, you'll need much computational power. If your filter kernel is 64 samples in length, which in fact is not that long, you'll need 64 multiplications to get just one output sample. If you want to process several channels, the speed that you require would rise even more. Another downside are memory requirements. All intermediate values of the output signal would have to be stored in memory while all of the kernel is applied. You would need the length of the kernel, times the amount of channels, of storage memory. On top of that, consider the output delay of the FIR filter. Only once the whole filter kernel is applied to an input sample, you will know what the outcome is. A delay of the length of the filter kernel is introduced in your signal, and depending of the length of the kernel, this can be very noticable in a live application.

ASRC6.png

Filters: IIR filter

With an IIR filter, an output sample not only depends on the input, but also output samples are taken into account. IIR filters have none of the downsides that FIR filters have. Kernels are short, therefore quickly applied, output delay is basically one sample, and required memory is also much less. Ideal right? Sure, but there are things to consider. If your output signal depends on other output samples, there is a very real chance of your filter function to run out of control. The gain of your filter function can never exceed unity, or else your filter works as an oscillator! This is why the coefficients of the IIR filter are chosen very carefully. Also the response of the filter may be not that clean compared to a FIR. But if the IIR is well designed, it can be a very good low pass filter which we require.

ASRC7.png

Math at work! This is an actual example of a IIR filter, with a 2kHz low pass kernel. Notice how the fast changes (e.g. the high frequencies) are filtered out in the data output, while the lower frequencies are all still present.

IIR1.png

Serializing an IIR filter

Having this IIR filter is of course great, but what if we have to filter more than one channel? Can we input several channels at once? Not without modification. The registers that store intermediate values have to be changed for memory blocks so they can store the values for more than one channel. These M4K blocks inside an Altera Cyclone can hold 4096 bits. With a 32 bit audio word width, this comes down to 128 addresses. This is the maximum amount of channels we can hold in a single M4K block, more channels and we have to combine several memory blocks for one filter tap. Because it takes one clock cycle for the memory to read the stored value, some additional delays have to be inserted in the data and address lines in order for the filter to work properly. In all, we end up with a block schematic like so:

IIR2.png

Block schematic of the ASRC

ASRC9.png