+make_do_samples(simple, , ,
+ simple_interp_store, simple_interp_get, )
+
+static noinline int do_samples_noise(int ch, int ns, int ns_to)
+{
+ int level, shift, bit;
+ int ret = -1, d;
+
+ s_chan[ch].spos += s_chan[ch].sinc * (ns_to - ns);
+ while (s_chan[ch].spos >= 28*0x10000)
+ {
+ d = skip_block(ch);
+ if (d)
+ ret = ns_to;
+ s_chan[ch].spos -= 28*0x10000;
+ }
+
+ // modified from DrHell/shalma, no fraction
+ level = (spu.spuCtrl >> 10) & 0x0f;
+ level = 0x8000 >> level;
+
+ for (; ns < ns_to; ns++)
+ {
+ spu.dwNoiseCount += 2;
+ if (spu.dwNoiseCount >= level)
+ {
+ spu.dwNoiseCount -= level;
+ shift = (spu.dwNoiseVal >> 10) & 0x1f;
+ bit = (0x69696969 >> shift) & 1;
+ if (spu.dwNoiseVal & 0x8000)
+ bit ^= 1;
+ spu.dwNoiseVal = (spu.dwNoiseVal << 1) | bit;
+ }
+
+ ChanBuf[ns] = (signed short)spu.dwNoiseVal;
+ }
+
+ return ret;
+}
+
+#ifdef HAVE_ARMV5
+// asm code; lv and rv must be 0-3fff
+extern void mix_chan(int start, int count, int lv, int rv);
+extern void mix_chan_rvb(int start, int count, int lv, int rv, int *rvb);
+#else
+static void mix_chan(int start, int count, int lv, int rv)
+{
+ int *dst = SSumLR + start * 2;
+ const int *src = ChanBuf + start;
+ int l, r;
+
+ while (count--)
+ {
+ int sval = *src++;
+
+ l = (sval * lv) >> 14;
+ r = (sval * rv) >> 14;
+ *dst++ += l;
+ *dst++ += r;
+ }
+}
+
+static void mix_chan_rvb(int start, int count, int lv, int rv, int *rvb)
+{
+ int *dst = SSumLR + start * 2;
+ int *drvb = rvb + start * 2;
+ const int *src = ChanBuf + start;
+ int l, r;
+
+ while (count--)
+ {
+ int sval = *src++;
+
+ l = (sval * lv) >> 14;
+ r = (sval * rv) >> 14;
+ *dst++ += l;
+ *dst++ += r;
+ *drvb++ += l;
+ *drvb++ += r;
+ }
+}
+#endif
+
+// 0x0800-0x0bff Voice 1
+// 0x0c00-0x0fff Voice 3
+static noinline void do_decode_bufs(int which, int start, int count)
+{
+ const int *src = ChanBuf + start;
+ unsigned short *dst = &spu.spuMem[0x800/2 + which*0x400/2];
+ int cursor = spu.decode_pos + start;
+
+ while (count-- > 0)
+ {
+ cursor &= 0x1ff;
+ dst[cursor] = *src++;
+ cursor++;
+ }
+
+ // decode_pos is updated and irqs are checked later, after voice loop
+}
+
+////////////////////////////////////////////////////////////////////////
+// MAIN SPU FUNCTION
+// here is the main job handler...
+// basically the whole sound processing is done in this fat func!
+////////////////////////////////////////////////////////////////////////
+
+void do_samples(unsigned int cycles_to)
+{
+ const int ns_from = 0;
+ int ns,ns_to,ns_len;
+ int volmult = spu_config.iVolume;
+ int ch,d,silentch;
+ int cycle_diff;
+
+ cycle_diff = cycles_to - spu.cycles_played;
+ if (cycle_diff < -2*1048576 || cycle_diff > 2*1048576)
+ {
+ //xprintf("desync %u %d\n", cycles_to, cycle_diff);
+ spu.cycles_played = cycles_to;
+ return;
+ }