+}
+
+#define make_do_samples(name, fmod_code, interp_start, interp1_code, interp2_code, interp_end) \
+static noinline int do_samples_##name( \
+ int (*decode_f)(void *context, int ch, int *SB), void *ctx, \
+ int ch, int ns_to, int *SB, int sinc, int *spos, int *sbpos) \
+{ \
+ int ns, d, fa; \
+ int ret = ns_to; \
+ interp_start; \
+ \
+ for (ns = 0; ns < ns_to; ns++) \
+ { \
+ fmod_code; \
+ \
+ *spos += sinc; \
+ while (*spos >= 0x10000) \
+ { \
+ fa = SB[(*sbpos)++]; \
+ if (*sbpos >= 28) \
+ { \
+ *sbpos = 0; \
+ d = decode_f(ctx, ch, SB); \
+ if (d && ns < ret) \
+ ret = ns; \
+ } \
+ \
+ interp1_code; \
+ *spos -= 0x10000; \
+ } \
+ \
+ interp2_code; \
+ } \
+ \
+ interp_end; \
+ \
+ return ret; \
+}
+
+#define fmod_recv_check \
+ if(spu.s_chan[ch].bFMod==1 && iFMod[ns]) \
+ sinc = FModChangeFrequency(SB, spu.s_chan[ch].iRawPitch, ns)
+
+make_do_samples(default, fmod_recv_check, ,
+ StoreInterpolationVal(SB, sinc, fa, spu.s_chan[ch].bFMod==2),
+ ChanBuf[ns] = iGetInterpolationVal(SB, sinc, *spos, spu.s_chan[ch].bFMod==2), )
+make_do_samples(noint, , fa = SB[29], , ChanBuf[ns] = fa, SB[29] = fa)
+
+#define simple_interp_store \
+ SB[28] = 0; \
+ SB[29] = SB[30]; \
+ SB[30] = SB[31]; \
+ SB[31] = fa; \
+ SB[32] = 1
+
+#define simple_interp_get \
+ if(sinc<0x10000) /* -> upsampling? */ \
+ InterpolateUp(SB, sinc); /* --> interpolate up */ \
+ else InterpolateDown(SB, sinc); /* --> else down */ \
+ ChanBuf[ns] = SB[29]
+
+make_do_samples(simple, , ,
+ simple_interp_store, simple_interp_get, )