public int synthesis(Packet op) {
        Info vi = vd.vi;

        // first things first.  Make sure decode is ready
        opb.readinit(op.packet_base, op.packet, op.bytes);

        // Check the packet type
        if (opb.read(1) != 0) {
            // Oops.  This is not an audio data packet
            return (-1);
        }

        // read our mode and pre/post windowsize
        int _mode = opb.read(vd.modebits);
        if (_mode == -1) {
            return (-1);
        }

        mode = _mode;
        W = vi.mode_param[mode].blockflag;
        if (W != 0) {
            lW = opb.read(1);
            nW = opb.read(1);
            if (nW == -1) {
                return (-1);
            }
        } else {
            lW = 0;
            nW = 0;
        }

        // more setup
        granulepos = op.granulepos;
        sequence = op.packetno - 3; // first block is third packet
        eofflag = op.e_o_s;

        // alloc pcm passback storage
        pcmend = vi.blocksizes[W];
        if (pcm.length < vi.channels) {
            pcm = new float[vi.channels][];
        }
        for (int i = 0; i < vi.channels; i++) {
            if (pcm[i] == null || pcm[i].length < pcmend) {
                pcm[i] = new float[pcmend];
            } else {
                for (int j = 0; j < pcmend; j++) {
                    pcm[i][j] = 0;
                }
            }
        }

        // unpack_header enforces range checking
        int type = vi.map_type[vi.mode_param[mode].mapping];
        return (FuncMapping.mapping_P[type].inverse(this, vd.mode[mode]));
    }