 rev [0] * samples [3]) >> 11;
}
#endif /* SPC_GAUSSIAN_FAST_INTERP */

#ifndef SPC_GAUSSIAN_FAST_AMP
#define gaussian_fast_amp   apply_amp
#endif /* SPC_GAUSSIAN_FAST_AMP */

#ifndef SPC_GAUSSIAN_SLOW_INTERP
static inline int gaussian_slow_interp( int16_t const* samples,
                                        int32_t position,
                                        int16_t const* fwd,
                                        int16_t const* rev )
{
    int output;
    samples += position >> 12;
    output = (fwd [0] * samples [0]) & ~0xFFF;
    output = (output + fwd [1] * samples [1]) & ~0xFFF;
    output = (output + rev [1] * samples [2]) >> 12;
    output = (int16_t) (output * 2);
    output += ((rev [0] * samples [3]) >> 12) * 2;
    return CLAMP16( output );
}
#endif /* SPC_GAUSSIAN_SLOW_INTERP */

#ifndef SPC_GAUSSIAN_SLOW_AMP
static inline int gaussian_slow_amp( struct voice_t* voice, int output,
                                     int *amp_0, int *amp_1 )
{
    output = apply_gen_envx( voice, output ) & ~1;
    output = apply_gen_volume( voice, output, amp_0, amp_1 );
    return output;
}
#endif /* SPC_GAUSSIAN_SLOW_AMP */

#define interp      gaussian_slow_interp
#define apply_amp   gaussian_slow_amp

#else /* SPC_NOINTERP */

#ifndef SPC_LINEAR_INTERP
static inline int linear_interp( int16_t const* samples, int32_t position )
{
    int32_t fraction = position & 0xfff;
    int16_t const* pos = (samples + (position >> 12)) + 1;
    return pos[0] + ((fraction * (pos[1] - pos[0])) >> 12);
}
#endif /* SPC_LINEAR_INTERP */

#define interp( samp, pos, fwd, rev ) \
    linear_interp( (samp), (pos) )

#ifndef SPC_LINEAR_AMP
#define linear_amp   apply_gen_amp
#endif /* SPC_LINEAR_AMP */

#define apply_amp    linear_amp
#endif /* SPC_NOINTERP */


#if !SPC_NOECHO

#ifndef SPC_DSP_ECHO_APPLY
/* Init FIR filter */
static inline void echo_init( struct Spc_Dsp* this )
{
    this->fir.pos = 0;
    ci->memset( this->fir.buf, 0, sizeof this->fir.buf );
}

/* Apply FIR filter */
static inline void echo_apply(struct Spc_