protected Int32 ParseChannel(BinaryReader fd, float time)
        {
            //
            // channel name is next. the tag for this must be CHNM
            //
            String       chnmTag = new String(fd.ReadChars(4));
            String       channelName;
            String       sizeTag;
            String       dataFormatTag;
            Int32        chnmSize;
            Int32        arrayLength;
            Int32        bufferLength;
            Int32        bytesRead = 0;
            Int32        mask;
            Int32        chnmSizeToRead;
            Int32        paddingSize;
            Int32        index;
            CacheChannel channel = null;

            if (chnmTag != "CHNM")
            {
                return(0);
            }
            bytesRead += 4;
            //
            // Next comes a 32 bit int that tells us how long the channel name is
            //
            chnmSize   = ReadInt(fd);
            bytesRead += 4;
            //
            // The string is padded out to 32 bit boundaries,
            // so we may need to read more than chnmSize
            //
            mask           = 3;
            chnmSizeToRead = (chnmSize + mask) & (~mask);
            --chnmSize;
            channelName = new String(fd.ReadChars(chnmSize));
            channel     = Channels[channelName];
            paddingSize = chnmSizeToRead - chnmSize;
            if (paddingSize > 0)
            {
                fd.ReadChars(paddingSize);
            }
            bytesRead += chnmSizeToRead;
            //
            // Next is the SIZE field, which tells us the length of the data array
            //
            sizeTag = new String(fd.ReadChars(4));
            if (sizeTag != "SIZE")
            {
                throw new FileLoadException("SIZE section missing in cache file " + FileName);
            }
            bytesRead += 4;
            //
            // Next 32 bit int is the size of the array size variable,
            // this is always 4, so we'll ignore it for now
            // though we could use it as a sanity check.
            //
            fd.ReadChars(4);
            bytesRead += 4;
            //
            //finally the actual size of the array
            //
            arrayLength = ReadInt(fd);
            bytesRead  += 4;
            //
            // data format tag
            //
            dataFormatTag = new String(fd.ReadChars(4));
            //
            // buffer length - how many bytes is the actual data
            //
            bufferLength = ReadInt(fd);
            bytesRead   += 8;
            Vixen.VertexArray verts      = new Vixen.VertexArray("position float 3", arrayLength);
            float[]           floatArray = new float[arrayLength * verts.VertexSize];

            if (dataFormatTag == "FVCA")                        // FVCA == Float Vector Array
            {
                if (bufferLength != arrayLength * 3 * 4)
                {
                    throw new FileLoadException("size inconsistency in cache file " + FileName);
                }
                for (int i = 0; i < arrayLength; i++)
                {
                    int   j = i * verts.VertexSize;
                    float x = ReadFloat(fd);
                    float y = ReadFloat(fd);
                    float z = ReadFloat(fd);
                    floatArray[j]     = x;
                    floatArray[j + 1] = y;
                    floatArray[j + 2] = z;
                }
            }
            else if (dataFormatTag == "DVCA")                   // DVCA == Double Vector Array
            {
                if (bufferLength != arrayLength * 3 * 8)
                {
                    throw new FileLoadException("size inconsistency in cache file " + FileName);
                }
                for (int i = 0; i < arrayLength; i++)
                {
                    int   j = i * verts.VertexSize;
                    float x = ReadDouble(fd);
                    float y = ReadDouble(fd);
                    float z = ReadDouble(fd);
                    floatArray[j]     = x;
                    floatArray[j + 1] = y;
                    floatArray[j + 2] = z;
                }
            }
            else
            {
                throw new FileLoadException("Unknown data tag " + dataFormatTag + " in cache file " + FileName);
            }
            bytesRead += bufferLength;
            verts.AddVertices(floatArray, arrayLength);
            float t = time + TimePerFrame / 2.0f - channel.StartTime;

            index = (Int32)(t / TimePerFrame);
            _root.SetSource(index, verts);
            Log("\ti = " + index + " t = " + t);
            return(bytesRead);
        }