Пример #1
0
        private void InitializeDecodeComponents()
        {
            var hcaInfo = HcaInfo;

            if (!_ath.Initialize(hcaInfo.AthType, hcaInfo.SamplingRate))
            {
                throw new HcaException(ErrorMessages.GetAthInitializationFailed(), ActionResult.AthInitFailed);
            }
            var decodeParams = _decodeParams;
            var cipherType   = decodeParams.CipherTypeOverrideEnabled ? decodeParams.OverriddenCipherType : hcaInfo.CipherType;

            if (!_cipher.Initialize(cipherType, decodeParams.Key1, decodeParams.Key2))
            {
                throw new HcaException(ErrorMessages.GetCiphInitializationFailed(), ActionResult.CiphInitFailed);
            }
            var channels = _channels = new Channel[0x10];

            for (var i = 0; i < channels.Length; ++i)
            {
                channels[i] = Channel.CreateDefault();
            }
            var  r = new byte[10];
            uint b = hcaInfo.ChannelCount / hcaInfo.CompR03;

            if (hcaInfo.CompR07 != 0 && b > 1)
            {
                uint rIndex = 0;
                for (uint i = 0; i < hcaInfo.CompR03; ++i, rIndex += b)
                {
                    switch (b)
                    {
                    case 2:
                    case 3:
                        r[rIndex]     = 1;
                        r[rIndex + 1] = 2;
                        break;

                    case 4:
                        r[rIndex]     = 1;
                        r[rIndex + 1] = 2;
                        if (hcaInfo.CompR04 == 0)
                        {
                            r[rIndex + 2] = 1;
                            r[rIndex + 3] = 2;
                        }
                        break;

                    case 5:
                        r[rIndex]     = 1;
                        r[rIndex + 1] = 2;
                        if (hcaInfo.CompR04 <= 2)
                        {
                            r[rIndex + 3] = 1;
                            r[rIndex + 4] = 2;
                        }
                        break;

                    case 6:
                    case 7:
                        r[rIndex]     = 1;
                        r[rIndex + 1] = 2;
                        r[rIndex + 4] = 1;
                        r[rIndex + 5] = 2;
                        break;

                    case 8:
                        r[rIndex]     = 1;
                        r[rIndex + 1] = 2;
                        r[rIndex + 4] = 1;
                        r[rIndex + 5] = 2;
                        r[rIndex + 6] = 1;
                        r[rIndex + 7] = 2;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("b");
                    }
                }
            }
            for (uint i = 0; i < hcaInfo.ChannelCount; ++i)
            {
                channels[i].Type   = r[i];
                channels[i].Value3 = (uint)(hcaInfo.CompR06 + hcaInfo.CompR07);
                channels[i].Count  = (uint)(hcaInfo.CompR06 + (r[i] != 2 ? hcaInfo.CompR07 : 0));
            }
        }
Пример #2
0
        public int WriteWaveHeader(byte[] stream, AudioParams audioParams)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            var hcaInfo = HcaInfo;

            if (hcaInfo.LoopFlag && audioParams.InfiniteLoop)
            {
                // See remarks of AudioParams.InfiniteLoop.
                throw new HcaException(ErrorMessages.GetInvalidParameter(nameof(audioParams.InfiniteLoop)), ActionResult.InvalidParameter);
            }
            var minimumHeaderBufferSize = GetMinWaveHeaderBufferSize();

            if (stream.Length < minimumHeaderBufferSize)
            {
                throw new HcaException(ErrorMessages.GetBufferTooSmall(minimumHeaderBufferSize, stream.Length), ActionResult.BufferTooSmall);
            }
            var sampleBits = GetSampleBitsFromParams();
            var wavRiff    = WaveRiffSection.CreateDefault();
            var wavNote    = WaveNoteSection.CreateDefault();
            var wavData    = WaveDataSection.CreateDefault();

            wavRiff.FmtType          = (ushort)(_decodeParams.Mode != SamplingMode.R32 ? 1 : 3);
            wavRiff.FmtChannels      = (ushort)hcaInfo.ChannelCount;
            wavRiff.FmtBitCount      = (ushort)(sampleBits > 0 ? sampleBits : sizeof(float));
            wavRiff.FmtSamplingRate  = hcaInfo.SamplingRate;
            wavRiff.FmtSamplingSize  = (ushort)(wavRiff.FmtBitCount / 8 * wavRiff.FmtChannels);
            wavRiff.FmtSamplesPerSec = wavRiff.FmtSamplingRate * wavRiff.FmtSamplingSize;
            if (hcaInfo.Comment != null)
            {
                wavNote.NoteSize = 4 + hcaInfo.CommentLength + 1;
                if ((wavNote.NoteSize & 3) != 0)
                {
                    wavNote.NoteSize += 4 - (wavNote.NoteSize & 3);
                }
            }

            var totalBlockCount = hcaInfo.BlockCount;

            if (hcaInfo.LoopFlag)
            {
                totalBlockCount += (hcaInfo.LoopEnd - hcaInfo.LoopStart) * audioParams.SimulatedLoopCount;
            }
            wavData.DataSize = totalBlockCount * 0x80 * 8 * wavRiff.FmtSamplingSize;
            wavRiff.RiffSize = (uint)(0x1c + (hcaInfo.Comment != null ? wavNote.NoteSize : 0) + Marshal.SizeOf(wavData) + wavData.DataSize);

            var bytesWritten = stream.Write(wavRiff, 0);

            if (hcaInfo.Comment != null)
            {
                var address = bytesWritten;
                bytesWritten += stream.Write(wavNote, bytesWritten);
                stream.Write(hcaInfo.Comment, bytesWritten);
                bytesWritten  = address + 8 + (int)wavNote.NoteSize;
                bytesWritten += 8 + (int)wavNote.NoteSize;
            }
            bytesWritten += stream.Write(wavData, bytesWritten);
            return(bytesWritten);
        }
Пример #3
0
        private int DecodeToWaveR32(byte[] blockData, int blockIndex)
        {
            var hcaInfo = HcaInfo;

            if (blockData == null)
            {
                throw new ArgumentNullException(nameof(blockData));
            }
            if (blockData.Length < hcaInfo.BlockSize)
            {
                throw new HcaException(ErrorMessages.GetInvalidParameter(nameof(blockData) + "." + nameof(blockData.Length)), ActionResult.InvalidParameter);
            }
            var checksum = HcaHelper.Checksum(blockData, 0);

            if (checksum != 0)
            {
                throw new HcaException(ErrorMessages.GetChecksumNotMatch(0, checksum), ActionResult.ChecksumNotMatch);
            }
            _cipher.Decrypt(blockData);
            var d     = new DataBits(blockData, hcaInfo.BlockSize);
            var magic = d.GetBit(16);

            if (magic != 0xffff)
            {
                throw new HcaException(ErrorMessages.GetMagicNotMatch(0xffff, magic), ActionResult.MagicNotMatch);
            }
            var    a        = (d.GetBit(9) << 8) - d.GetBit(7);
            var    channels = _channels;
            var    ath      = _ath;
            string site     = null;

            try {
                int i;

                for (i = 0; i < hcaInfo.ChannelCount; ++i)
                {
                    site = $"Decode1({i.ToString()})";
                    channels.Decode1(i, d, hcaInfo.CompR09, a, ath.Table);
                }

                for (i = 0; i < 8; ++i)
                {
                    for (var j = 0; j < hcaInfo.ChannelCount; ++j)
                    {
                        site = $"Decode2({i.ToString()}/{j.ToString()})";
                        channels.Decode2(j, d);
                    }

                    for (var j = 0; j < hcaInfo.ChannelCount; ++j)
                    {
                        site = $"Decode3({i.ToString()}/{j.ToString()})";
                        channels.Decode3(j, hcaInfo.CompR09, hcaInfo.CompR08, (uint)(hcaInfo.CompR07 + hcaInfo.CompR06), hcaInfo.CompR05);
                    }

                    for (var j = 0; j < hcaInfo.ChannelCount - 1; ++j)
                    {
                        site = $"Decode4({i.ToString()}/{j.ToString()})";
                        channels.Decode4(j, j + 1, i, (uint)(hcaInfo.CompR05 - hcaInfo.CompR06), hcaInfo.CompR06, hcaInfo.CompR07);
                    }

                    for (var j = 0; j < hcaInfo.ChannelCount; ++j)
                    {
                        site = $"Decode5({i.ToString()}/{j.ToString()})";
                        channels.Decode5(j, i);
                    }
                }

                return(blockData.Length);
            } catch (IndexOutOfRangeException ex) {
                const string message  = "Index access exception detected. It is probably because you are using an incorrect HCA key pair while decoding a type 56 HCA file.";
                var          siteInfo = $"Site: {site} @ block {blockIndex.ToString()}";
                var          err      = message + Environment.NewLine + siteInfo;
                throw new HcaException(err, ActionResult.DecodeFailed, ex);
            }
        }