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)); } }
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); }
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); } }