Dsp* this,
        uint8_t* const echo_ptr, int* out_0, int* out_1)
{
    int fb_0 = GET_LE16SA( echo_ptr     );
    int fb_1 = GET_LE16SA( echo_ptr + 2 );
        
    /* Keep last 8 samples */
    int (* const fir_ptr) [2] = this->fir.buf + this->fir.pos;
    this->fir.pos = (this->fir.pos + 1) & (FIR_BUF_HALF - 1);

    fir_ptr [           0] [0] = fb_0;
    fir_ptr [           0] [1] = fb_1;
    /* duplicate at +8 eliminates wrap checking below */
    fir_ptr [FIR_BUF_HALF] [0] = fb_0;
    fir_ptr [FIR_BUF_HALF] [1] = fb_1;

    fb_0 *= this->fir.coeff [0];
    fb_1 *= this->fir.coeff [0];

    #define DO_PT( i ) \
        fb_0 += fir_ptr [i] [0] * this->fir.coeff [i]; \
        fb_1 += fir_ptr [i] [1] * this->fir.coeff [i];

    DO_PT( 1 )
    DO_PT( 2 )
    DO_PT( 3 )
    DO_PT( 4 )
    DO_PT( 5 )
    DO_PT( 6 )
    DO_PT( 7 )

    #undef DO_PT

    *out_0 = fb_0;
    *out_1 = fb_1;
}
#endif /* SPC_DSP_ECHO_APPLY */

#ifndef SPC_DSP_ECHO_FEEDBACK
/* Feedback into echo buffer */
static inline void echo_feedback( struct Spc_Dsp* this, uint8_t *echo_ptr,
                                  int echo_0, int echo_1, int fb_0, int fb_1 )
{
    int e0 = (echo_0 >> 7) + ((fb_0 * this->r.g.echo_feedback) >> 14);
    int e1 = (echo_1 >> 7) + ((fb_1 * this->r.g.echo_feedback) >> 14);
    e0 = CLAMP16( e0 );
    SET_LE16A( echo_ptr    , e0 );
    e1 = CLAMP16( e1 );
    SET_LE16A( echo_ptr + 2, e1 );
}
#endif /* SPC_DSP_ECHO_FEEDBACK */

#ifndef SPC_DSP_GENERATE_OUTPUT
/* Generate final output */
static inline void echo_output( struct Spc_Dsp* this, int global_muting,
    int global_vol_0, int global_vol_1, int chans_0, int chans_1, 
    int fb_0, int fb_1, int* out_0, int* out_1 )
{
    *out_0 = (chans_0 * global_vol_0 + fb_0 * this->r.g.echo_volume_0)
                >> global_muting;
    *out_1 = (chans_1 * global_vol_1 + fb_1 * this->r.g.echo_volume_1)
                >> global_muting;
}
#endif /* SPC_DSP_GENERATE_OUTPUT */

#define mix_output echo_output

#else /* SPC_NOECHO */

#ifndef SPC_DSP_GENERATE_OUTPUT
/* Gen