/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <param name="channel"></param> private void ExportDSPChannel(string filePath, DSPChannel channel) { using (BinaryWriterExt w = new BinaryWriterExt(new FileStream(filePath, FileMode.Create))) { w.BigEndian = true; var samples = channel.NibbleCount * 7 / 8; w.Write(samples); w.Write(channel.NibbleCount); w.Write(Frequency); w.Write(channel.LoopFlag); w.Write(channel.Format); w.Write(2); w.Write(channel.NibbleCount - 2); w.Write(2); foreach (var v in channel.COEF) { w.Write(v); } w.Write(channel.Gain); w.Write(channel.InitialPredictorScale); w.Write(channel.InitialSampleHistory1); w.Write(channel.InitialSampleHistory2); w.Write(channel.LoopPredictorScale); w.Write(channel.LoopSampleHistory1); w.Write(channel.LoopSampleHistory2); w.Write((short)0); w.Write(new byte[0x14]); w.Write(channel.Data); if (w.BaseStream.Position % 0x8 != 0) { w.Write(new byte[0x08 - w.BaseStream.Position % 0x08]); } w.BaseStream.Close(); } }
private void FromDSP(byte[] data) { Channels.Clear(); using (BinaryReaderExt r = new BinaryReaderExt(new MemoryStream(data))) { r.BigEndian = true; r.ReadInt32(); var nibbleCount = r.ReadInt32(); Frequency = r.ReadInt32(); var channel = new DSPChannel(); channel.LoopFlag = r.ReadInt16(); channel.Format = r.ReadInt16(); var LoopStartOffset = r.ReadInt32(); var LoopEndOffset = r.ReadInt32(); var CurrentAddress = r.ReadInt32(); for (int k = 0; k < 0x10; k++) { channel.COEF[k] = r.ReadInt16(); } channel.Gain = r.ReadInt16(); channel.InitialPredictorScale = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.InitialSampleHistory2 = r.ReadInt16(); channel.LoopPredictorScale = r.ReadInt16(); channel.LoopSampleHistory1 = r.ReadInt16(); channel.LoopSampleHistory2 = r.ReadInt16(); r.ReadInt16(); // padding r.Seek(0x60); channel.NibbleCount = nibbleCount; channel.LoopStart = LoopStartOffset - CurrentAddress; channel.Data = r.ReadBytes((int)Math.Ceiling(nibbleCount / 2d)); Channels.Add(channel); r.BaseStream.Close(); } }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <returns></returns> public static DSP ToDSP(byte[] data) { DSP dsp = new DSP(); dsp.Channels.Clear(); using (BinaryReaderExt r = new BinaryReaderExt(new MemoryStream(data))) { r.BigEndian = true; if (new string(r.ReadChars(7)) != " HALPST") { throw new NotSupportedException("Invalid HPS file"); } r.ReadByte(); dsp.Frequency = r.ReadInt32(); var channelCount = r.ReadInt32(); if (channelCount != 2) { throw new NotSupportedException("Only HPS with 2 channels are currently supported"); } for (int i = 0; i < channelCount; i++) { var channel = new DSPChannel(); channel.LoopFlag = r.ReadInt16(); channel.Format = r.ReadInt16(); var SA = r.ReadInt32(); var EA = r.ReadInt32(); var CA = r.ReadInt32(); for (int k = 0; k < 0x10; k++) { channel.COEF[k] = r.ReadInt16(); } channel.Gain = r.ReadInt16(); channel.InitialPredictorScale = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.InitialSampleHistory1 = r.ReadInt16(); channel.NibbleCount = EA - CA; channel.LoopStart = SA - CA; dsp.Channels.Add(channel); } // read blocks r.Position = 0x80; Dictionary <int, int> OffsetToLoopPosition = new Dictionary <int, int>(); List <byte> channelData1 = new List <byte>(); List <byte> channelData2 = new List <byte>(); while (true) { var pos = r.Position; var length = r.ReadInt32(); var lengthMinusOne = r.ReadInt32(); var next = r.ReadInt32(); { var initPS = r.ReadInt16(); var initsh1 = r.ReadInt16(); var initsh2 = r.ReadInt16(); var gain = r.ReadInt16(); } { var initPS = r.ReadInt16(); var initsh1 = r.ReadInt16(); var initsh2 = r.ReadInt16(); var gain = r.ReadInt16(); } var extra = r.ReadInt32(); OffsetToLoopPosition.Add((int)pos, channelData1.Count * 2); channelData1.AddRange(r.ReadBytes(length / 2)); channelData2.AddRange(r.ReadBytes(length / 2)); if (next < r.Position || next == -1) { if (next != -1) { foreach (var c in dsp.Channels) { c.LoopStart = OffsetToLoopPosition[next]; } } break; } else { r.Position = (uint)next; } } dsp.Channels[0].Data = channelData1.ToArray(); dsp.Channels[1].Data = channelData2.ToArray(); } return(dsp); }
/*public void ToHPS() * { * * }*/ #endregion #region WAVE private void FromWAVE(byte[] wavFile) { if (wavFile.Length < 0x2C) { throw new NotSupportedException("File is not a valid WAVE file"); } Channels.Clear(); using (BinaryReader r = new BinaryReader(new MemoryStream(wavFile))) { if (new string(r.ReadChars(4)) != "RIFF") { throw new NotSupportedException("File is not a valid WAVE file"); } r.BaseStream.Position = 0x14; var comp = r.ReadInt16(); var channelCount = r.ReadInt16(); Frequency = r.ReadInt32(); r.ReadInt32(); // block rate r.ReadInt16(); // block align var bpp = r.ReadInt16(); if (comp != 1) { throw new NotSupportedException("Compressed WAVE files not supported"); } if (bpp != 16) { throw new NotSupportedException("Only 16 bit WAVE formats accepted"); } while (new string(r.ReadChars(4)) != "data") { var skip = r.ReadInt32(); r.BaseStream.Position += skip; } var channelSizes = r.ReadInt32() / channelCount / 2; List <List <short> > channels = new List <List <short> >(); for (int i = 0; i < channelCount; i++) { channels.Add(new List <short>()); } for (int i = 0; i < channelSizes; i++) { foreach (var v in channels) { v.Add(r.ReadInt16()); } } Channels.Clear(); foreach (var data in channels) { var c = new DSPChannel(); var ss = data.ToArray(); c.COEF = GcAdpcmCoefficients.CalculateCoefficients(ss); c.Data = GcAdpcmEncoder.Encode(ss, c.COEF); c.NibbleCount = c.Data.Length * 2; c.InitialPredictorScale = c.Data[0]; Channels.Add(c); } } }