"Molot" and "Limiter №6" plugins page (and Tokyo Dawn Labs stuff too)

Using SoX resampler in VST plugins

If you hear about SoX resampler and what SoX library is for the first time go and see the links.

Using SoX resampler inside plugin is quite simple. First, append these files of libsox (see the image, sox-14.3.2 was used in my example):

Next, SoX interface uses integer sample type. But SoX resampler uses floating point. To avoid multiple conversion it’s better to use not libsox interface but functions in rate.c directly. And also to add interface to access internal functions outside of rate.c file. This can be done by directly including “rate.c” file in your file:

 * the only way to access private SoX rate functions is to include rate file here
#include “rate.c”

 * now implement our interface to access private SoX rate functions

#include “soxrate.h”

struct soxrate {
    rate_t          rate;
    rate_shared_t   shared;

    int             linear_phase;
    double          bandwidth;
    int             allow_aliasing;

static int      g_libsox_init = 0;

struct soxrate *
soxrate_create(double factor, int linear_phase, double bandwidth, int allow_aliasing)
    struct soxrate *r;

    if (g_libsox_init++ == 0) {
        // init globals

    r = calloc(1, sizeof(*r));
    if (r == NULL)
        return NULL;
    r->linear_phase = linear_phase;
    r->bandwidth = bandwidth;
    r->allow_aliasing = allow_aliasing;

    rate_init(&r->rate, &r->shared, factor, Very, -1, linear_phase ? 50 : 0, bandwidth, allow_aliasing ? sox_true : sox_false);

    return r;

See complete implementation in soxrate.c file in [archive]. This archive contains Molot source code cutted in such a way so only saturator has left. Project “molotsat.vcproj” uses standart Molot oversampler. Project “molotsat2.vcproj” uses SoX resampler. You can compare how they sounds.

The “C” interface h-file for soxrate.c is quite simple:

#ifndef _soxrate_h_
#define _soxrate_h_

 * abstract interface to SoX rate internal interface

struct soxrate;

struct soxrate  *soxrate_create(double factor, int linear_phase, double bandwidth, int allow_aliasing);
struct soxrate  *soxrate_clone(struct soxrate *param_r);

void    soxrate_delete(struct soxrate *r);

void    soxrate_process(struct soxrate *r);
void    soxrate_flush(struct soxrate *r);

const double    *soxrate_output(struct soxrate *r, size_t *n);

double  *soxrate_input(struct soxrate *r, size_t n);


But VST SDK is a set of C++ classes. So it’s better to implement Upsampler/Downsampler C++ classes. Upsampler’s main function looks like this:

Upsampler::processSample(double x, double *y)
    double *input_fifo;
    const double *output_fifo;
    size_t size;

    // feed input
    input_fifo = soxrate_input(m_rate, 1);

    _ASSERT(input_fifo != NULL);

    *input_fifo = x;

    // process!

    // get new fifo
    size = m_xN;

    output_fifo = soxrate_output(m_rate, &size);

    if (size < m_xN) {
        _ASSERT(size == 0);

        memset(y, 0, m_xN * sizeof(double));
    } else {
        _ASSERT(size == m_xN);

        memcpy(y, output_fifo, m_xN * sizeof(double));

The downsampler’s function is not complex too:

Downsampler::processSample(double *x)
    double *input_fifo, y;
    const double *output_fifo;
    size_t size;

    // feed input
    input_fifo = soxrate_input(m_rate, m_xN);

    _ASSERT(input_fifo != NULL);

    memcpy(input_fifo, x, m_xN * sizeof(double));

    // process!

    // get new fifo
    size = 1;

    output_fifo = soxrate_output(m_rate, &size);

    if (size < 1) {
        y = 0.0;
    } else {
        y = *output_fifo;

    return y;

See moloteng.h and moloteng2.cpp files in archive. Also I used dithering there but you can remove it.

Usage of these upsampler/downsampler classes is simple:

ChannelCompressor::processSample(double x)
    double over[MAX_OVERSAMPLING];
    unsigned int i;

    m_upsampler.processSample(x * m_gain, over);

    for (i = 0; i < m_oversampling; i++) {
        //over[i] = m_saturator.processSample(over[i]) * m_master;
    return m_downsampler.processSample(over);

It works! But too-o-o-o slow! Why? Because SoX resampler is optimized not for easy 2x or 4x upsampling/downsampling but for fractional resampling (44.1 -> 48 kHz for example). It uses DFT for filter implementation regardless of filter type. There’s a comment in rate.c:

       /* Start setting up post-stage; TODO don’t use dft for short filters */

How to make it faster? The answer is not to use DFT but to use simple FIR filter. The idea:

  1. Use SoX library only to get FIR responses for filters
  2. Implement FIR filters convolution

I did FIR responses for upsampler and downsampler for cases of 2x, 4x and so on oversampling in this way:

            char str[256];
            double *f;
            int i, num_taps;

            f = lsx_design_lpf(0.931, 1.0, 2.0, sox_true, 34.0 / 33.0 * 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 2.0, sox_false, 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 4.0, sox_true, 34.0 / 33.0 * 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 4.0, sox_false, 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 8.0, sox_true, 34.0 / 33.0 * 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 8.0, sox_false, 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 16.0, sox_true, 34.0 / 33.0 * 170.0, &num_taps, 0);
            //f = lsx_design_lpf(0.931, 1.0, 16.0, sox_false, 170.0, &num_taps, 0);

            for (i = 0; i < num_taps; i++) {
                if (f[i] != 0.0)
                    sprintf(str, “%0.15e,\n”, f[i]);
                    strcpy(str, “0,\n”);

                printf(“%s”, str);


Parameters for functions were get like sox utility used in maximum quality mode. Aliasing for upsampling is allowed to make FIR shorter but is not allowed for downsampling.

Finally I’ve got files with numbers. For example fir4_dn.dat (used for 4x downsampling):

 * generated using libsox library
 * lsx_design_lpf(0.931, 1.0, 4.0, sox_false, 170.0, &num_taps, 0);

Now all I have to do is to write fast convolution implementation and some helpers. For speed up I used SSE and 32-bit floating point to make 4 multiplications per time. I’m not a great programmer for speed and optimizations so my implementation is far from perfect but fast enough.

// fir must be aligned! fir_size must be %16!
FirFilter::fast_convolve(float *x)
    unsigned int i;
    double y;

    // convolution

    __m128 xy1, xy2, xy3, xy4;

    xy1 = _mm_setzero_ps();
    xy2 = _mm_setzero_ps();
    xy3 = _mm_setzero_ps();
    xy4 = _mm_setzero_ps();

    for (i = 0; i < m_fir_size; i += 16) {
        xy1 = _mm_add_ps(xy1,
                _mm_loadu_ps(x + i),
                _mm_load_ps(m_fir + i)
        xy2 = _mm_add_ps(xy2,
                _mm_loadu_ps(x + i + 4),
                _mm_load_ps(m_fir + i + 4)
        xy3 = _mm_add_ps(xy3,
                _mm_loadu_ps(x + i + 8),
                _mm_load_ps(m_fir + i + 8)
        xy4 = _mm_add_ps(xy4,
                _mm_loadu_ps(x + i + 12),
                _mm_load_ps(m_fir + i + 12)

    xy1 = _mm_add_ps(
            _mm_add_ps(xy1, xy2),
            _mm_add_ps(xy3, xy4));

    float xy_flt[4];

    _mm_storeu_ps(xy_flt, xy1);

    y = xy_flt[0] + xy_flt[1] + xy_flt[2] + xy_flt[3];

    return y;

Some more details for source code. As upsampling is done by zero inserting, e.g. append (x, 0, 0, 0) for case of 4x oversampling in the input of the filter and get (y1, y2, y3, y4) to get oversampled output some optimization was used. The FIR is splitted into 4 parts to avoid multiplications on zero (see FirFilterN class). UpsamplerNx/DownsamplerNx are the classes for SoX FIR filters. Upsampler/Downsampler are the classes for standart Molot oversampling.

See the complete source code in this [archive]. This archive contains source code for simple acceleration limiter plugin. The idea for plugin is to limit vinyl cutter speed. But in this plugin simple waveshaping is used so it’s just an example and not intended for real work.

The original Molot oversampler also included in both archives so you can compare how the different oversampling implementations differs in sound.

Hope it helps.

One response to “Using SoX resampler in VST plugins

  1. Pingback: 不不不,Sox 明显好了一大截 | RSA1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: