static byte apu_dpcm(dpcm_t chan) {
        int freq, bit_pos;

        /* reg0: 7=irq gen, 6=looping, 3-0=pointer to clock table
         ** reg1: output dc level, 7 bits unsigned
         ** reg2: 8 bits of 64-byte aligned address offset : $C000 + (value * 64)
         ** reg3: length, (value * 16) + 1
         */
        if (chan.enabled) {
            freq = dpcm_clocks[chan.regs[0] & 0x0F];
            chan.phaseacc -= (float) apu_incsize; /* # of cycles per sample */

            while (chan.phaseacc < 0) {
                chan.phaseacc += freq;

                if (0 == chan.length) {
                    if ((chan.regs[0] & 0x40) != 0) {
                        apu_dpcmreset(chan);
                    } else {
                        if ((chan.regs[0] & 0x80) != 0) /* IRQ Generator */ {
                            chan.irq_occurred = true;
                            n2a03_irq();
                        }
                        break;
                    }
                }

                chan.bits_left--;
                bit_pos = 7 - (chan.bits_left & 7);
                if (7 == bit_pos) {
                    chan.cur_byte = chan.cpu_mem.read(chan.address);
                    chan.address++;
                    chan.length--;
                }

                if ((chan.cur_byte & (1 << bit_pos)) != 0) //            chan.regs[1]++;
                {
                    chan.vol++;
                } else //            chan.regs[1]--;
                {
                    chan.vol--;
                }
            }
        }

        if (chan.vol > 63) {
            chan.vol = 63;
        } else if (chan.vol < -64) {
            chan.vol = -64;
        }

        return (byte) (chan.vol >> 1);
    }