Exemplo n.º 1
0
        public void Init(StreamReader.IReader fileReader, UInt64 offset, ref VGM_Stream vgmStream, bool InitReader, UInt64 fileLength)
        {
            byte[] mibBuffer   = new byte[0x10];
            byte[] testBuffer  = new byte[0x10];
            byte[] testBuffer2 = new byte[0x10];
            byte[] testBuffer3 = new byte[0x10];

            //bool doChannelUpdate=true;
            //bool bDoUpdateInterleave=true;

            UInt64 loopStart  = 0;
            UInt64 loopEnd    = 0;
            UInt64 interleave = 0;
            UInt64 readOffset = offset;

            UInt64[] loopStartPoints      = new UInt64[0x10];
            int      loopStartPointsCount = 0;

            UInt64[] loopEndPoints      = new UInt64[0x10];
            int      loopEndPointsCount = 0;

            byte[] emptyLine        = new byte[0x10];
            bool   loopToEnd        = false;
            bool   forceNoLoop      = false;
            bool   bolSaveEmptyLine = true;

            int    i, channel_count = 0;
            bool   interleave_found = false;
            UInt64 tstCount         = 0;

            UInt64[] emptyLineOffset      = new UInt64[100];
            uint     emptyLineCount       = 0;
            uint     max_interleave       = 0;
            uint     max_interleave_index = 0;

            // Initialize loop point to 0
            for (i = 0; i < 0x10; i++)
            {
                loopStartPoints[i] = 0;
                loopEndPoints[i]   = 0;
                testBuffer[i]      = 0;
                emptyLine[i]       = 0;
            }

            //if (this.Filename.ToUpper().Contains(".MIB"))

            /* Search for interleave value & loop points */
            /* Get the first 16 values */
            mibBuffer = fileReader.Read(offset, 0x10);
            if (MemoryReader.memcmp(mibBuffer, emptyLine, 0x10, 0))
            {
                tstCount = 0x10;
                //readOffset += 0x10;
            }
            else
            {
                tstCount = 0x0e;
            }

            do
            {
                testBuffer = fileReader.Read(readOffset, 0x10);

                // be sure to point to an interleave value
                if (!interleave_found)
                {
                    if (MemoryReader.memcmp(testBuffer, emptyLine, tstCount, 0x10 - tstCount))
                    {
                        // don't need to stock all empty lines :P
                        if (emptyLineCount >= 100)
                        {
                            emptyLineCount = 0;
                        }

                        if (emptyLineCount >= 1)
                        {
                            if ((readOffset - offset) > 0x60000)
                            {
                                bolSaveEmptyLine = false;
                            }
                        }

                        if (bolSaveEmptyLine)
                        {
                            emptyLineOffset[emptyLineCount] = readOffset;
                            emptyLineCount++;
                        }
                    }
                }

                // Loop Start ...
                if (testBuffer[0x01] == 0x06)
                {
                    if (loopStartPointsCount < 0x10)
                    {
                        loopStartPoints[loopStartPointsCount] = readOffset - offset - 0x10;
                        loopStartPointsCount++;
                    }
                }

                // Loop End ...
                if (((testBuffer[0x01] == 0x03) && (testBuffer[0x03] != 0x77)) ||
                    (testBuffer[0x01] == 0x01))
                {
                    if (loopEndPointsCount < 0x10)
                    {
                        loopEndPoints[loopEndPointsCount] = readOffset - offset;                 //-0x10;
                        loopEndPointsCount++;
                    }

                    if (testBuffer[0x01] == 0x01)
                    {
                        forceNoLoop = true;
                    }
                }

                if (testBuffer[0x01] == 0x04)
                {
                    // 0x04 loop points flag can't be with a 0x03 loop points flag
                    if (loopStartPointsCount < 0x10)
                    {
                        if ((readOffset - offset) == 0)
                        {
                            loopStartPoints[loopStartPointsCount] = 0;
                        }
                        else
                        {
                            loopStartPoints[loopStartPointsCount] = readOffset - offset;
                        }

                        loopStartPointsCount++;

                        // Loop end value is not set by flags ...
                        // go until end of file
                        loopToEnd = true;
                    }
                }
                readOffset += 0x10;
            } while (readOffset < (offset + fileLength));

            // Try to find biggest interleave value
            if (emptyLineCount > 1)
            {
                for (uint count = 1; count < emptyLineCount; count++)
                {
                    if (((uint)(emptyLineOffset[count] - emptyLineOffset[count - 1])) > max_interleave)
                    {
                        max_interleave       = (uint)(emptyLineOffset[count] - emptyLineOffset[count - 1]);
                        max_interleave_index = count;
                    }
                }
                if (max_interleave_index != 0)
                {
                    interleave = (uint)(emptyLineOffset[max_interleave_index] - emptyLineOffset[0]);
                }
            }

            if ((testBuffer[0] == 0x0c) && (testBuffer[1] == 0))
            {
                forceNoLoop = true;
            }

            if (channel_count == 0)
            {
                channel_count = 1;
            }

            // Calc Loop Points & Interleave ...
            if (loopStartPointsCount >= channel_count)
            {
                // can't get more then 0x10 loop point !
                // and need at least 2 loop points
                if ((loopStartPointsCount <= 0x0F) && (loopStartPointsCount >= 2))
                {
                    // Always took the first 2 loop points
                    interleave = loopStartPoints[loopStartPointsCount - 1] - loopStartPoints[loopStartPointsCount - 2];
                    loopStart  = loopStartPoints[1];

                    // Can't be one channel .mib with interleave values
                    if ((interleave > 0) && (channel_count == 1))
                    {
                        channel_count = 2;
                    }
                }
                else
                {
                    loopStart = 0;
                }
            }

            if (loopEndPointsCount >= channel_count)
            {
                // can't get more then 0x10 loop point !
                // and need at least 2 loop points
                if ((loopEndPointsCount <= 0x0F) && (loopEndPointsCount >= 2))
                {
                    if (loopEndPointsCount == 4)
                    {
                        if (interleave == 0)
                        {
                            interleave = loopEndPoints[3] - loopEndPoints[1];
                        }
                        else
                        {
                            interleave = loopEndPoints[loopEndPointsCount - 1] - loopEndPoints[loopEndPointsCount - 2];
                        }
                    }
                    loopEnd = loopEndPoints[loopEndPointsCount - 1];

                    if (interleave >= 0x10)
                    {
                        if (channel_count == 1)
                        {
                            channel_count = 2;
                        }
                    }
                }
                else
                {
                    loopToEnd = false;
                    loopEnd   = 0;
                }
            }

            if (loopToEnd)
            {
                loopEnd = fileLength;
            }

            // force no loop
            if (forceNoLoop)
            {
                loopEnd = 0;
            }

            if ((interleave > 0x10) && (channel_count == 1))
            {
                channel_count = 2;
            }

            if (interleave <= 0)
            {
                interleave = 0x10;
            }

            /* build the VGMSTREAM */
            VGM_Utils.allocate_vgmStream(ref vgmStream, channel_count, (loopEnd != 0));

            /* fill in the vital statistics */
            vgmStream.vgmDecoder = new PSX_Decoder();

            if (channel_count == 1)
            {
                vgmStream.vgmLayout = new NoLayout();
            }
            else
            {
                vgmStream.vgmLayout = new Interleave();
            }

            vgmStream.vgmChannelCount        = channel_count;
            vgmStream.vgmInterleaveBlockSize = (int)interleave;
            vgmStream.vgmLoopFlag            = (loopEnd != 0);

            if (m_Description == null)
            {
                vgmStream.vgmSampleRate = 44100;
            }
            else
            {
                if (System.IO.Path.GetExtension(m_Description).ToUpper() == ".MIB")
                {
                    vgmStream.vgmSampleRate = 44100;
                }
            }

            vgmStream.vgmTotalSamples = (int)(fileLength / (UInt64)16 / (UInt64)(channel_count * 28));

            if (loopEnd != 0)
            {
                if (vgmStream.vgmChannelCount == 1)
                {
                    vgmStream.vgmLoopStartSample = (int)loopStart / 16 * 18;
                    vgmStream.vgmLoopEndSample   = (int)loopEnd / 16 * 28;
                }
                else
                {
                    if (loopStart == 0)
                    {
                        vgmStream.vgmLoopStartSample = 0;
                    }
                    else
                    {
                        vgmStream.vgmLoopStartSample = (int)(((UInt64)(((loopStart / interleave) - 1) * interleave)) / (UInt64)((16 * 14 * channel_count) / channel_count));

                        if (loopStart % interleave != 0)
                        {
                            vgmStream.vgmLoopStartSample += (int)(((UInt64)((loopStart % interleave) - 1) / (UInt64)(16 * 14 * channel_count)));
                        }
                    }

                    if (loopEnd == fileLength)
                    {
                        vgmStream.vgmLoopEndSample = (int)((UInt64)loopEnd / (UInt64)((16 * 28) / channel_count));
                    }
                    else
                    {
                        vgmStream.vgmLoopEndSample = (int)((UInt64)(((loopEnd / interleave) - 1) * interleave) / (UInt64)((16 * 14 * channel_count) / channel_count));

                        if (loopEnd % interleave != 0)
                        {
                            vgmStream.vgmLoopEndSample += (int)((UInt64)((loopEnd % interleave) - 1) / (UInt64)(16 * 14 * channel_count));
                        }
                    }
                }
            }
            if (InitReader)
            {
                for (i = 0; i < channel_count; i++)
                {
                    vgmStream.vgmChannel[i].currentOffset = offset + (interleave * (UInt64)i);
                    vgmStream.vgmChannel[i].fReader       = (StreamReader.IReader)Activator.CreateInstance(fileReader.GetType());
                    vgmStream.vgmChannel[i].fReader.Open(fileReader.GetFilename());
                    vgmStream.vgmChannel[i].fReader.SetSessionID(fileReader.GetSessionID());
                }
            }
        }
Exemplo n.º 2
0
        public void Init(StreamReader.IReader fileReader, UInt64 offset, ref VGM_Stream vgmStream, bool InitReader, UInt64 fileLength)
        {
            bool   loop_flag         = false;
            UInt32 loop_start_sample = 0;
            UInt32 loop_start_offset;
            UInt32 loop_end_sample = 0;
            UInt32 loop_end_offset;

            Int16 coef1 = 0;
            Int16 coef2 = 0;

            UInt16 xor_start = 0;
            UInt16 xor_mult  = 0;
            UInt16 xor_add   = 0;

            int i;

            int channel_count = fileReader.Read_8Bits(offset + 0x07);

            /* check version signature, read loop info */
            UInt16 version_signature = fileReader.Read_16bitsBE(offset + 0x12);
            UInt64 criOffset         = (UInt64)(fileReader.Read_16bitsBE(offset + 2) + 4);

            /* encryption */
            if (version_signature == 0x0408)
            {
                if (!find_key(fileReader, offset, ref xor_start, ref xor_mult, ref xor_add))
                {
                    return;
                }
            }

            UInt32 ainf_info_length = 0;

            if (fileReader.Read_32bitsBE(offset + 0x24) == 0x41494E46) /* AINF Header */
            {
                ainf_info_length = fileReader.Read_32bitsBE(offset + 0x28);
            }

            if (criOffset - ainf_info_length - 6 >= 0x38)
            {   /* enough space for loop info? */
                loop_flag         = (fileReader.Read_32bitsBE(offset + 0x24) != 0);
                loop_start_sample = (fileReader.Read_32bitsBE(offset + 0x28));
                loop_start_offset = fileReader.Read_32bitsBE(offset + 0x2C);
                loop_end_sample   = fileReader.Read_32bitsBE(offset + 0x30);
                loop_end_offset   = fileReader.Read_32bitsBE(offset + 0x34);
            }

            /* build the VGMSTREAM */
            VGM_Utils.allocate_vgmStream(ref vgmStream, channel_count, loop_flag);

            vgmStream.vgmChannelCount = channel_count;
            vgmStream.vgmSampleRate   = (int)fileReader.Read_32bitsBE(offset + 0x08);
            vgmStream.vgmTotalSamples = (int)fileReader.Read_32bitsBE(offset + 0x0C);

            vgmStream.vgmDecoder = new ADXENC_Decoder();

            if (channel_count == 1)
            {
                vgmStream.vgmLayout = new NoLayout();
            }
            else
            {
                vgmStream.vgmLayout = new Interleave();
            }

            vgmStream.vgmLoopFlag = loop_flag;

            if (loop_flag)
            {
                vgmStream.vgmLoopStartSample = (int)loop_start_sample;
                vgmStream.vgmLoopEndSample   = (int)loop_end_sample;
            }

            /* high-pass cutoff frequency, always 500 that I've seen */
            UInt16 cutoff = fileReader.Read_16bitsBE(offset + 0x10);

            /* calculate filter coefficients */
            {
                double x, y, z, a, b, c;

                x = cutoff;
                y = vgmStream.vgmSampleRate;
                z = Math.Cos(2.0 * Math.PI * x / y);

                a = Math.Sqrt(2) - z;
                b = Math.Sqrt(2) - 1.0;
                c = (a - Math.Sqrt((a + b) * (a - b))) / b;

                coef1 = (Int16)Math.Floor(c * 8192);
                coef2 = (Int16)Math.Floor(c * c * -4096);
            }

            vgmStream.vgmInterleaveBlockSize = 18;

            if (InitReader)
            {
                for (i = 0; i < channel_count; i++)
                {
                    vgmStream.vgmChannel[i].fReader = (StreamReader.IReader)Activator.CreateInstance(fileReader.GetType());;
                    vgmStream.vgmChannel[i].fReader.Open(fileReader.GetFilename());
                    vgmStream.vgmChannel[i].fReader.SetSessionID(fileReader.GetSessionID());

                    vgmStream.vgmChannel[i].adpcm_coef[0] = coef1;
                    vgmStream.vgmChannel[i].adpcm_coef[1] = coef2;
                    vgmStream.vgmChannel[i].startOffset   = vgmStream.vgmChannel[i].currentOffset = offset + criOffset + (UInt64)((vgmStream.vgmInterleaveBlockSize * i));

                    int j;
                    vgmStream.vgmChannel[i].adx_channels = channel_count;
                    vgmStream.vgmChannel[i].adx_xor      = xor_start;
                    vgmStream.vgmChannel[i].adx_mult     = xor_mult;
                    vgmStream.vgmChannel[i].adx_add      = xor_add;

                    for (j = 0; j < i; j++)
                    {
                        VGM_Utils.adx_next_key(ref vgmStream.vgmChannel[i]);
                    }
                }
            }
        }