示例#1
0
        private static void ReadSeekBlock(BinaryReader reader, BxstmStructure structure)
        {
            SizedReference reference = structure.Blocks.FirstOrDefault(x => x.Type == ReferenceType.StreamSeekBlock);

            if (reference == null)
            {
                return;
            }

            reader.BaseStream.Position = reference.AbsoluteOffset;
            StreamInfo info = structure.StreamInfo;

            if (reader.ReadUTF8(4) != "SEEK")
            {
                throw new InvalidDataException("Unknown or invalid SEEK block");
            }

            if (reader.ReadInt32() != reference.Size)
            {
                throw new InvalidDataException("SEEK block size in main header doesn't match size in SEEK header");
            }

            int bytesPerEntry       = 4 * info.ChannelCount;
            int numSeekTableEntries = info.SampleCount.DivideByRoundUp(info.SamplesPerSeekTableEntry);

            int seekTableSize = bytesPerEntry * numSeekTableEntries;

            byte[] tableBytes = reader.ReadBytes(seekTableSize);

            structure.SeekTable = tableBytes.ToShortArray()
                                  .DeInterleave(2, info.ChannelCount);
        }
示例#2
0
        private static void ReadRegionBlock(BinaryReader reader, BxstmStructure structure)
        {
            SizedReference reference = structure.Blocks.FirstOrDefault(x => x.Type == ReferenceType.StreamRegionBlock);

            if (reference == null)
            {
                return;
            }

            reader.BaseStream.Position = reference.AbsoluteOffset;

            if (reader.ReadUTF8(4) != "REGN")
            {
                throw new InvalidDataException("Unknown or invalid REGN block");
            }

            if (reader.ReadInt32() != reference.Size)
            {
                throw new InvalidDataException("REGN block size in main header doesn't match size in REGN header");
            }

            StreamInfo info         = structure.StreamInfo;
            int        startAddress = reference.AbsoluteOffset + 8 + info.RegionReference.Offset;
            var        regions      = new List <RegionInfo>();

            for (int i = 0; i < info.RegionCount; i++)
            {
                reader.BaseStream.Position = startAddress + info.RegionInfoSize * i;

                var entry = new RegionInfo
                {
                    StartSample = reader.ReadInt32(),
                    EndSample   = reader.ReadInt32()
                };

                for (int c = 0; c < info.ChannelCount; c++)
                {
                    entry.Channels.Add(new GcAdpcmContext(reader));
                }
                regions.Add(entry);
            }

            structure.Regions = regions;
        }
示例#3
0
        private static void ReadInfoBlock(BinaryReader reader, BxstmStructure structure)
        {
            SizedReference reference =
                structure.Blocks.FirstOrDefault(x => x.Type == ReferenceType.StreamInfoBlock ||
                                                x.Type == ReferenceType.WaveInfoBlock) ??
                throw new InvalidDataException("File has no INFO block");

            reader.BaseStream.Position = reference.AbsoluteOffset;
            if (reader.ReadUTF8(4) != "INFO")
            {
                throw new InvalidDataException("Unknown or invalid INFO block");
            }

            if (reader.ReadInt32() != reference.Size)
            {
                throw new InvalidDataException("INFO block size in main header doesn't match size in INFO header");
            }

            switch (reference.Type)
            {
            case ReferenceType.StreamInfoBlock:
                int baseOffset  = (int)reader.BaseStream.Position;
                var streamInfo  = new Reference(reader, baseOffset);
                var trackInfo   = new Reference(reader, baseOffset);
                var channelInfo = new Reference(reader, baseOffset);

                ReadStreamInfo(reader, structure, streamInfo);
                ReadTrackInfo(reader, structure, trackInfo);
                ReadChannelInfo(reader, structure, channelInfo);
                break;

            case ReferenceType.WaveInfoBlock:
                structure.StreamInfo  = StreamInfo.ReadBfwav(reader, structure.Version);
                structure.ChannelInfo = ChannelInfo.ReadBfstm(reader);
                break;
            }
        }
示例#4
0
        private static void ReadDataBlock(BinaryReader reader, BxstmStructure structure, bool readAudioData)
        {
            SizedReference reference =
                structure.Blocks.FirstOrDefault(x => x.Type == ReferenceType.StreamDataBlock ||
                                                x.Type == ReferenceType.StreamPrefetchDataBlock ||
                                                x.Type == ReferenceType.WaveDataBlock) ??
                throw new InvalidDataException("File has no DATA block");

            StreamInfo info = structure.StreamInfo;

            reader.BaseStream.Position = reference.AbsoluteOffset;

            string blockId = reader.ReadUTF8(4);

            if (blockId != "DATA" && blockId != "PDAT")
            {
                throw new InvalidDataException("Unknown or invalid DATA block");
            }

            if (reader.ReadInt32() != reference.Size)
            {
                throw new InvalidDataException("DATA block size in main header doesn't match size in DATA header");
            }

            if (!readAudioData)
            {
                return;
            }

            if (reference.IsType(ReferenceType.WaveDataBlock))
            {
                int audioDataLength = Common.SamplesToBytes(info.SampleCount, info.Codec);
                structure.AudioData = CreateJaggedArray <byte[][]>(info.ChannelCount, audioDataLength);
                int baseOffset = (int)reader.BaseStream.Position;

                for (int i = 0; i < info.ChannelCount; i++)
                {
                    reader.BaseStream.Position = baseOffset + structure.ChannelInfo.WaveAudioOffsets[i];
                    structure.AudioData[i]     = reader.ReadBytes(audioDataLength);
                }
            }
            else if (reference.IsType(ReferenceType.StreamDataBlock))
            {
                int audioOffset = reference.AbsoluteOffset + info.AudioReference.Offset + 8;
                reader.BaseStream.Position = audioOffset;
                int audioDataLength = reference.Size - (audioOffset - reference.AbsoluteOffset);
                int outputSize      = Common.SamplesToBytes(info.SampleCount, info.Codec);

                structure.AudioData = reader.BaseStream.DeInterleave(audioDataLength, info.InterleaveSize,
                                                                     info.ChannelCount, outputSize);
            }
            else if (reference.IsType(ReferenceType.StreamPrefetchDataBlock))
            {
                structure.PrefetchData = new List <PrefetchData>();
                int count = reader.ReadInt32();

                for (int i = 0; i < count; i++)
                {
                    structure.PrefetchData.Add(PrefetchData.ReadPrefetchData(reader, info));
                }

                reader.BaseStream.Position = structure.PrefetchData[0].AudioData.AbsoluteOffset;
                structure.AudioData        = reader.BaseStream.DeInterleave(structure.PrefetchData[0].Size, info.InterleaveSize,
                                                                            info.ChannelCount, structure.PrefetchData[0].Size);
            }
        }