+ if (block == spu.pSpuIrq)
+ break;
+ flags = block[1];
+ block += 16;
+ if (flags & 1) { // 1: stop/loop
+ block = s_chan->pLoop;
+ }
+ pos += 28 << 16;
+ }
+
+ if (pos < end)
+ {
+ sinc_inv = s_chan->sinc_inv;
+ if (sinc_inv == 0)
+ sinc_inv = s_chan->sinc_inv = (0x80000000u / (uint32_t)sinc) << 1;
+
+ pos -= s_chan->spos;
+ *upd_samples = (((uint64_t)pos * sinc_inv) >> 32) + 1;
+ //xprintf("ch%02d: irq sched: %3d %03d\n",
+ // ch, *upd_samples, *upd_samples * 60 * 263 / 44100);
+ }
+}
+
+#define make_do_samples(name, fmod_code, interp_start, interp_store, interp_get, interp_end) \
+static noinline int name(int *dst, \
+ int (*decode_f)(void *context, int ch, int *SB), void *ctx, \
+ int ch, int ns_to, sample_buf *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->SB[(*sbpos)++]; \
+ if (*sbpos >= 28) \
+ { \
+ *sbpos = 0; \
+ d = decode_f(ctx, ch, sb->SB); \
+ if (d && ns < ret) \
+ ret = ns; \
+ } \
+ \
+ interp_store; \
+ *spos -= 0x10000; \
+ } \
+ \
+ interp_get; \
+ } \
+ \
+ interp_end; \
+ \
+ return ret; \
+}
+
+// helpers for simple linear interpolation: delay real val for two slots,
+// and calc the two deltas, for a 'look at the future behaviour'
+#define simple_interp_store \
+ sb->SB[28] = 0; \
+ sb->SB[29] = sb->SB[30]; \
+ sb->SB[30] = sb->SB[31]; \
+ sb->SB[31] = fa; \
+ sb->SB[32] = 1
+
+#define simple_interp_get \
+ if(sinc<0x10000) /* -> upsampling? */ \
+ InterpolateUp(sb, sinc); /* --> interpolate up */ \
+ else InterpolateDown(sb, sinc); /* --> else down */ \
+ dst[ns] = sb->SB[29]
+
+make_do_samples(do_samples_nointerp, , fa = sb->SB[29],
+ , dst[ns] = fa, sb->SB[29] = fa)
+make_do_samples(do_samples_simple, , ,
+ simple_interp_store, simple_interp_get, )
+make_do_samples(do_samples_gauss, , ,
+ StoreInterpolationGaussCubic(sb, fa),
+ dst[ns] = GetInterpolationGauss(sb, *spos), )
+make_do_samples(do_samples_cubic, , ,
+ StoreInterpolationGaussCubic(sb, fa),
+ dst[ns] = GetInterpolationCubic(sb, *spos), )
+make_do_samples(do_samples_fmod,
+ sinc = FModChangeFrequency(spu.s_chan[ch].iRawPitch, ns, iFMod), ,
+ StoreInterpolationGaussCubic(sb, fa),
+ dst[ns] = GetInterpolationGauss(sb, *spos), )
+
+INLINE int do_samples_adpcm(int *dst,
+ int (*decode_f)(void *context, int ch, int *SB), void *ctx,
+ int ch, int ns_to, int fmod, sample_buf *sb, int sinc, int *spos, int *sbpos)
+{
+ int interp = spu.interpolation;
+ if (fmod == 1)
+ return do_samples_fmod(dst, decode_f, ctx, ch, ns_to, sb, sinc, spos, sbpos);
+ if (fmod)
+ interp = 2;
+ switch (interp) {
+ case 0:
+ return do_samples_nointerp(dst, decode_f, ctx, ch, ns_to, sb, sinc, spos, sbpos);
+ case 1:
+ return do_samples_simple (dst, decode_f, ctx, ch, ns_to, sb, sinc, spos, sbpos);
+ default:
+ return do_samples_gauss (dst, decode_f, ctx, ch, ns_to, sb, sinc, spos, sbpos);
+ case 3:
+ return do_samples_cubic (dst, decode_f, ctx, ch, ns_to, sb, sinc, spos, sbpos);