private static void VerifyData(HpsStructure structure) { structure.SampleCount = structure.Channels.First().SampleCount; if (structure.Channels.Any(x => x.SampleCount != structure.SampleCount)) { throw new InvalidDataException("Channels have differing sample counts"); } int startOffset = structure.Blocks.Last().NextOffset; if (startOffset == -1) { return; } int currentNibble = 0; //Find the loop start block foreach (HpsBlock block in structure.Blocks) { if (block.Offset == startOffset) { structure.Looping = true; structure.LoopStart = GcAdpcmMath.NibbleCountToSampleCount(currentNibble); for (int i = 0; i < structure.Channels.Count; i++) { structure.Channels[i].Loop = block.Channels[i].Context; } } currentNibble += block.FinalNibble + 1; } }
public static (byte[] adpcm, short[] coefs) GenerateAdpcmEmpty(int sampleCount) { var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)]; var coefs = new short[16]; return(adpcm, coefs); }
internal GcAdpcmChannel(GcAdpcmChannelBuilder b) { if (b.AlignedAdpcm.Length < GcAdpcmMath.SampleCountToByteCount(b.SampleCount)) { throw new ArgumentException("Audio array length is too short for the specified number of samples."); } UnalignedSampleCount = b.SampleCount; Adpcm = b.Adpcm; Pcm = b.Pcm; Coefs = b.Coefs; Gain = b.Gain; StartContext = new GcAdpcmContext(Adpcm[0], b.StartContext.Hist1, b.StartContext.Hist2); Alignment = b.GetAlignment(); LoopContextEx = b.GetLoopContext(); SeekTable = b.GetSeekTable(); //Grab the PCM data in case it was generated for the loop context or seek table if (!AlignmentNeeded) { Pcm = b.AlignedPcm; } }
public void AdpcmLengthIsCorrectAfterRealignment() { GcAdpcmChannel channel = GetBuilder(100).WithLoop(true, 10, 100).WithLoopAlignment(15).Build(); GcAdpcmChannel channel2 = channel.GetCloneBuilder().WithLoopAlignment(20).Build(); Assert.Equal(GcAdpcmMath.SampleCountToByteCount(110), channel2.GetAdpcmAudio().Length); }
private static GcAdpcmChannelBuilder GetBuilder(int sampleCount = 100) { var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)]; var coefs = new short[16]; return(new GcAdpcmChannelBuilder(adpcm, coefs, sampleCount)); }
public static RwavWaveInfo ReadBrwav(BinaryReader reader) { int baseOffset = (int)reader.BaseStream.Position; var info = new RwavWaveInfo(); info.Codec = (NwCodec)reader.ReadByte(); info.Looping = reader.ReadBoolean(); info.ChannelCount = reader.ReadByte(); reader.BaseStream.Position++; info.SampleRate = reader.ReadUInt16(); reader.BaseStream.Position += 2; info.LoopStart = GcAdpcmMath.NibbleToSample(reader.ReadInt32()); info.SampleCount = GcAdpcmMath.NibbleToSample(reader.ReadInt32()); info.ChannelInfoOffset = reader.ReadInt32(); info.InfoStructureLength = reader.ReadInt32(); var channelInfoOffsets = new int[info.ChannelCount]; reader.BaseStream.Position = baseOffset + info.ChannelInfoOffset; for (int i = 0; i < info.ChannelCount; i++) { channelInfoOffsets[i] = reader.ReadInt32(); } for (int i = 0; i < info.ChannelCount; i++) { reader.BaseStream.Position = baseOffset + channelInfoOffsets[i]; RwavChannelInfo channel = RwavChannelInfo.Read(reader, baseOffset); info.Channels.Add(channel); } return(info); }
public void ConstructorAssignmentWorks(int sampleCount) { var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)]; var coefs = new short[16]; var builder = new GcAdpcmChannelBuilder(adpcm, coefs, sampleCount); Assert.Equal(adpcm, builder.Adpcm); Assert.Equal(coefs, builder.Coefs); Assert.Equal(sampleCount, builder.SampleCount); }
public void ReturnsSameDataAfterCreation() { var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(100)]; var coefs = new short[16]; GcAdpcmChannel channel = new GcAdpcmChannelBuilder(adpcm, coefs, 100).Build(); Assert.Equal(100, channel.SampleCount); Assert.Same(adpcm, channel.Adpcm); Assert.Same(coefs, channel.Coefs); }
public static GcAdpcmChannel[] GenerateAdpcmChannelsEmpty(int sampleCount, int channelCount) { var channels = new GcAdpcmChannel[channelCount]; for (int i = 0; i < channelCount; i++) { var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)]; var coefs = new short[16]; channels[i] = new GcAdpcmChannelBuilder(adpcm, coefs, sampleCount).Build(); } return(channels); }
public static GcAdpcmFormat GenerateAdpcmEmpty(int sampleCount, int channelCount, int sampleRate, int samplesPerSeekTableEntry = 0x3800) { var channels = new GcAdpcmChannel[channelCount]; for (int i = 0; i < channelCount; i++) { var builder = new GcAdpcmChannelBuilder(new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)], new short[16], sampleCount); builder.WithSeekTable(new short[sampleCount.DivideByRoundUp(samplesPerSeekTableEntry) * 2], samplesPerSeekTableEntry, true); channels[i] = builder.Build(); } var adpcm = new GcAdpcmFormat(channels, sampleRate); return(adpcm); }
public static int BytesToSamples(int byteCount, NwCodec codec) { switch (codec) { case NwCodec.GcAdpcm: return(GcAdpcmMath.ByteCountToSampleCount(byteCount)); case NwCodec.Pcm16Bit: return(byteCount / 2); case NwCodec.Pcm8Bit: return(byteCount); default: return(0); } }
public static int SamplesToBytes(int sampleCount, NwCodec codec) { switch (codec) { case NwCodec.GcAdpcm: return(GcAdpcmMath.SampleCountToByteCount(sampleCount)); case NwCodec.Pcm16Bit: return(sampleCount * 2); case NwCodec.Pcm8Bit: return(sampleCount); default: return(0); } }
public unsafe GcAdpcmChannel EncodeChannel(short[] pcm) { int sampleCount = pcm.Length; var adpcm = new byte[GcAdpcmMath.SampleCountToByteCount(sampleCount)]; var info = new ADPCMINFO(); Encode(pcm, adpcm, ref info, (uint)sampleCount); var coefs = new short[16]; for (int i = 0; i < 16; i++) { coefs[i] = info.coef[i]; } return(new GcAdpcmChannel(adpcm, coefs, sampleCount)); }
public static void PrintSpecificMetadata(object structure, StringBuilder builder) { var bxstm = structure as BxstmStructure; if (bxstm == null) { throw new InvalidDataException("Could not parse file metadata."); } StreamInfo info = bxstm.StreamInfo; builder.AppendLine(); int calculatedSamples = (info.InterleaveCount - 1) * info.SamplesPerInterleave + GcAdpcmMath.ByteCountToSampleCount(info.LastBlockSizeWithoutPadding); builder.AppendLine($"Interleave Count: {info.InterleaveCount}"); builder.AppendLine($"Interleave Size: 0x{info.InterleaveSize:X}"); builder.AppendLine($"Samples per interleave: {info.SamplesPerInterleave}"); builder.AppendLine($"Last interleave size without padding: 0x{info.LastBlockSizeWithoutPadding:X}"); builder.AppendLine($"Last interleave size: 0x{info.LastBlockSize:X}"); builder.AppendLine($"Samples in last interleave block: {info.LastBlockSamples}"); builder.AppendLine($"Sample count from data size: {calculatedSamples}"); builder.AppendLine(); builder.AppendLine($"Samples per seek table entry: {info.SamplesPerSeekTableEntry}"); for (int i = 0; i < bxstm.TrackInfo?.Tracks.Count; i++) { builder.AppendLine(); builder.AppendLine($"Track {i}"); builder.AppendLine(new string('-', 25)); PrintTrackMetadata(bxstm.TrackInfo?.Tracks[i], builder); } if (info.Codec != NwCodec.GcAdpcm) { return; } GcAdpcm.PrintAdpcmMetadata(bxstm.ChannelInfo.Channels, builder); }
public void AdpcmLengthIsCorrectAfterBuilding() { GcAdpcmChannel channel = GetBuilder(100).WithLoop(true, 10, 100).Build(); Assert.Equal(GcAdpcmMath.SampleCountToByteCount(100), channel.GetAdpcmAudio().Length); }
public void AdpcmLengthIsCorrectAfterAlignment() { var channel = GetBuilder(100).WithLoop(true, 10, 100).WithLoopAlignment(15).Build(); Assert.Equal(GcAdpcmMath.SampleCountToByteCount(105), channel.GetAdpcmAudio().Length); }