A simple sample rate converter

This forum is for developers of Rack Extensions to discuss the RE SDK, share code, and offer tips to other developers.
User avatar
orthodox
RE Developer
Posts: 2185
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

Post 28 Dec 2021

This is a simple sample rate converter (source code for RE). It can only upsample or downsample by 2^n ratio, that's faster and just what is needed most of the time.

Although I didn't test it thoroughly, it should work.

EDIT: updated the attachment.
You do not have the required permissions to view the files attached to this post.

User avatar
orthodox
RE Developer
Posts: 2185
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

Post 29 Dec 2021

Sorry, there was a bug. I updated it in the first post.

User avatar
orthodox
RE Developer
Posts: 2185
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

Post 04 Jan 2022

HOW IT WORKS

All the work is done by a Brickwall Filter, which filters out the frequency content that can't be represented in lower sample rate. Here is an example of such filter response (suppressing all frequencies above 24kHz):

Image

Downsampling

Let's say we have a waveform at 96k sample rate that we would like to downsample to 48k:

Image

We apply the brickwall filter:

Image

Then take every second sample at 48k sample rate (we may choose even or odd ones, the resulting waveform is the same):

Image

Upsampling

Let's upsample the result we got above (@48k) back to 96k. We interleave the stream with zero samples:

Image

Then apply the brickwall filter:

Image

The result is the upsampled waveform.
Last edited by orthodox on 31 Mar 2022, edited 3 times in total.

User avatar
pongasoft
RE Developer
Posts: 394
Joined: 21 Apr 2016
Location: Las Vegas

Post 05 Jan 2022

Thank you for the explanation!

User avatar
orthodox
RE Developer
Posts: 2185
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

Post 10 Jan 2022

HOW IT WORKS 2 (on filters)

FIR filters

A FIR (Finite Impulse Response or stateless) filter is an array/vector of coefficients. An N-th order filter has N+1 coefficients. It is applied by calculating the next output sample as the dot product of the coefficients vector and the same number of last input samples:

Image

Symmetric FIR filters (where the coefficients remain the same in reverse order) have some useful properties, one of them being linear phase response, which means the filter effectively has zero phase shift across the entire frequency range, it just delays the filtered signal in time by N/2 samples, which can be compensated.

Filters can have even or odd order. Even-order filters have a central element (which matches the position in time of the output sample) and are often used for oversampling as interpolating filters (so that the existing input samples stay intact and only the "missing" samples are calculated).

This implementation uses an odd order (N=2^k-1). That means the latency of one resampling is 2^(k-1)-0.5 samples, but since it is done twice (both ways), the total latency of up/down-resampling is integer again (2^k-1).

Brickwall LP filter

The brickwall filter used in this implementation is a fragment of sinc function (which determines the cutoff frequency) modified by Dolph-Chebyshev window:

Image Image

Image

You can check out various other window functions here: (window functions). I prefer the Dolph-Chebyshev one as it allows for direct control over the ripple level (explained below).

A resampler is only as good as its low-pass filter. The brickwall low-pass filter has two quality measures: the transition band width and the ripple level:

Image

The ripple is the response variation in the pass and stop bands. In the pass-band it will lead to EQ coloring. The HF signal infiltrated through the stop-band will be mirrored onto the pass-band due to aliasing. It is a signal distortion and it should be made as lower as possible (or as necessary).

The transition band should be made as narrow that it doesn't overlap the audible range (<20kHz). It gets wider when you lower the ripple and shrinks if you increase the filter window size, but a larger window will also increase the CPU load. The choice of window size in this implementation is limited to degrees of 2. Here is the transition start frequency (that we would like to keep over 20kHz) depending on the required ripple level (k stands for the window size of 2^k):

Image

Image

44.1k sample rate is worse for resamplers, as there is only 2 kHz of room for the transition band, as compared to 4 kHz at 48k.

One other consideration is where to place the center of the transition band (the cutoff frequency). It is often placed right at the Nyquist frequency (of the lowest sample rate):

Image

That has some benefits: that only half the transition band resides below the Nyquist (which allows to reduce the window size and CPU load by half), and that the sinc function has many zeros at the sampling points so those may be skipped from the calculation. I prefer to place the transition band entirely below the Nyquist to get rid of any aliasing (despite that the aliasing could affect only the transition band):

Image

--------------------------------------------

I may have made mistakes in my choice of filter parameters, I learned all that stuff from Wikipedia and by experimenting. If you have any ideas or questions, please welcome.

  • Information
  • Who is online

    Users browsing this forum: No registered users and 1 guest