示例#1
0
        public void Decode(VGM_Stream vgmStream, VGM_Channel vgmChannel, ref short[] vgmOutput, int vgmChannelSpacing,
                           int vgmFirstSample, int vgmSamplesToDo, int vgmChannelNumber)
        {
            int vgmSampleCount, i;

            int framesin = vgmFirstSample / 32;

            int scale             = vgmChannel.fReader.Read_16bitsBE(vgmChannel.currentOffset + (UInt64)((framesin * 18) ^ vgmChannel.adx_xor)) + 1;
            int vgmSampleHistory1 = vgmChannel.adpcm_history_32bits_1;
            int vgmSampleHistory2 = vgmChannel.adpcm_history_32bits_2;
            int coef1             = vgmChannel.adpcm_coef[0];
            int coef2             = vgmChannel.adpcm_coef[1];
            int vgmSample;

            vgmFirstSample = vgmFirstSample % 32;

            for (i = vgmFirstSample, vgmSampleCount = 0; i < vgmFirstSample + vgmSamplesToDo; i++, vgmSampleCount += vgmChannelSpacing)
            {
                int sample_byte = vgmChannel.fReader.Read_8Bits(vgmChannel.currentOffset + (UInt64)((framesin * 18) + 2 + i / 2));

                sample_byte = (((i & 1) == 1) ? VGM_Utils.LOWNIBBLE_SIGNED(sample_byte) : VGM_Utils.HINIBBLE_SIGNED(sample_byte));
                vgmSample   = (sample_byte * scale);
                vgmSample  += (((coef1 * vgmSampleHistory1) + (coef2 * vgmSampleHistory2)) >> 12);
                vgmOutput[vgmStream.vgmSamplesBlockOffset + vgmSampleCount + vgmChannelNumber] = VGM_Utils.clamp16(vgmSample);

                vgmSampleHistory2 = vgmSampleHistory1;
                vgmSampleHistory1 = vgmSample;
            }

            vgmChannel.adpcm_history_32bits_1 = vgmSampleHistory1;
            vgmChannel.adpcm_history_32bits_2 = vgmSampleHistory2;

            if ((i % 32) == 0)
            {
                for (i = 0; i < vgmChannel.adx_channels; i++)
                {
                    VGM_Utils.adx_next_key(ref vgmChannel);
                }
            }
        }
示例#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]);
                    }
                }
            }
        }