/// <summary>
        /// Get the size of the data block.
        /// </summary>
        /// <returns></returns>
        public UInt32 GetSize(byte encoding, ref b_stm.InfoBlock wavInfo)
        {
            UInt32 size = 0x20;

            switch (encoding)
            {
            case EncodingTypes.PCM8:
                size += (UInt32)(pcm8.Length * pcm8[0].Length);
                int padd0 = pcm8[0].Length;
                while ((padd0) % 0x20 != 0)
                {
                    padd0 += 1;
                }
                padd0 -= pcm8[0].Length;
                size  += (UInt32)(padd0 * pcm8.Length);
                break;

            case EncodingTypes.PCM16:
                size += (UInt32)(pcm16.Length * pcm16[0].Length * 2);
                int padd1 = pcm16[0].Length * 2;
                while ((padd1) % 0x20 != 0)
                {
                    padd1 += 1;
                }
                padd1 -= (pcm16[0].Length * 2);
                size  += (UInt32)(padd1 * pcm16.Length);
                break;

            case EncodingTypes.DSP_ADPCM:
                size += (UInt32)(dspAdpcm.Length * dspAdpcm[0].Length);
                int padd2 = dspAdpcm[0].Length;
                while ((padd2) % 0x20 != 0)
                {
                    padd2 += 1;
                }
                padd2 -= dspAdpcm[0].Length;
                size  += (UInt32)(padd2 * dspAdpcm.Length);
                break;
            }

            return(size);
        }
        /// <summary>
        /// Get data from a b_stm.
        /// </summary>
        /// <param name="wavInfo"></param>
        /// <returns></returns>
        public object GetDataSTM(b_stm.StreamSoundInfo wavInfo, b_stm.InfoBlock info)
        {
            object returnValue = null;

            //See encoding.
            switch (wavInfo.encoding)
            {
            case EncodingTypes.PCM8:
                return(EncoderFactory.SignedPcm8ToPcm8(pcm8));

            case EncodingTypes.PCM16:
                return(pcm16);

            case EncodingTypes.DSP_ADPCM:
                List <DspAdpcmInfo> context = new List <DspAdpcmInfo>();
                foreach (b_stm.ChannelInfo c in info.channels)
                {
                    context.Add(c.dspAdpcmInfo);
                }
                return(EncoderFactory.DspApcmToPcm16(dspAdpcm, wavInfo.sampleCount, context.ToArray()));
            }

            return(returnValue);
        }
        /// <summary>
        /// Read a soundN'Stream block.
        /// </summary>
        /// <param name="br">The reader.</param>
        /// <param name="info">Stream info.</param>
        /// <param name="seek">Seek info for history.</param>
        public SoundNStreamDataBlock(ref BinaryDataReader br, b_stm.InfoBlock info)
        {
            //Read magic.
            br.ReadUInt32s(2);

            br.Position += info.streamSoundInfo.sampleDataOffset.offset;

            //Read the channels.
            switch (info.streamSoundInfo.encoding)
            {
            //PCM8.
            case EncodingTypes.PCM8:

                //New data array.
                pcm8 = new sbyte[info.channels.Count()][];

                //Read channel blocks.
                List <sbyte>[] channelData = new List <sbyte> [info.channels.Count()];

                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData[j] = new List <sbyte>();
                }

                for (int i = 0; i < info.streamSoundInfo.blockCount - 1; i++)
                {
                    //Read data.
                    for (int j = 0; j < info.channels.Count; j++)
                    {
                        channelData[j].AddRange(br.ReadSBytes((int)info.streamSoundInfo.oneBlockBytesize));
                    }
                }

                //Read last block.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData[j].AddRange(br.ReadSBytes((int)info.streamSoundInfo.lastBlockBytesize));
                    br.ReadBytes((int)(info.streamSoundInfo.lastBlockPaddedBytesize - info.streamSoundInfo.lastBlockBytesize));
                }

                //Convert data.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    pcm8[j] = channelData[j].ToArray();
                }

                break;

            //PCM16.
            case EncodingTypes.PCM16:

                //New data array.
                pcm16 = new Int16[info.channels.Count()][];

                //Read channel blocks.
                List <Int16>[] channelData2 = new List <Int16> [info.channels.Count()];

                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData2[j] = new List <Int16>();
                }

                for (int i = 0; i < info.streamSoundInfo.blockCount - 1; i++)
                {
                    //Read data.
                    for (int j = 0; j < info.channels.Count; j++)
                    {
                        channelData2[j].AddRange(br.ReadInt16s((int)info.streamSoundInfo.oneBlockSamples));
                    }
                }

                //Read last block.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData2[j].AddRange(br.ReadInt16s((int)info.streamSoundInfo.lastBlockSamples));
                    br.ReadBytes((int)(info.streamSoundInfo.lastBlockPaddedBytesize - info.streamSoundInfo.lastBlockBytesize));
                }

                //Convert data.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    pcm16[j] = channelData2[j].ToArray();
                }

                break;

            //DSP-ADPCM.
            case EncodingTypes.DSP_ADPCM:

                //New data array.
                dspAdpcm = new byte[info.channels.Count()][];

                //Read channel blocks.
                List <byte>[] channelData3 = new List <byte> [info.channels.Count()];

                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData3[j] = new List <byte>();
                }

                for (int i = 0; i < info.streamSoundInfo.blockCount - 1; i++)
                {
                    //Read data.
                    for (int j = 0; j < info.channels.Count; j++)
                    {
                        channelData3[j].AddRange(br.ReadBytes((int)info.streamSoundInfo.oneBlockBytesize));
                    }
                }

                //Read last block.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    channelData3[j].AddRange(br.ReadBytes((int)info.streamSoundInfo.lastBlockBytesize));
                    br.ReadBytes((int)(info.streamSoundInfo.lastBlockPaddedBytesize - info.streamSoundInfo.lastBlockBytesize));
                }

                //Convert data.
                for (int j = 0; j < info.channels.Count; j++)
                {
                    dspAdpcm[j] = channelData3[j].ToArray();
                }

                break;
            }
        }
        /// <summary>
        /// Write for BFSTM.
        /// </summary>
        /// <param name="bw">The writer.</param>
        /// <param name="wavInfo"></param>
        public void WriteSTM(ref BinaryDataWriter bw, b_stm.InfoBlock wavInfo, UInt32 numSamples)
        {
            bw.Write("DATA".ToCharArray());
            bw.Write(GetSize(wavInfo.streamSoundInfo.encoding, ref wavInfo));
            bw.Write(new byte[0x18]);

            //Update data.
            wavInfo.streamSoundInfo.oneBlockBytesize = 0x2000;
            switch (wavInfo.streamSoundInfo.encoding)
            {
            //PCM8.
            case EncodingTypes.PCM8:
                wavInfo.streamSoundInfo.oneBlockSamples   = wavInfo.streamSoundInfo.seekInfoIntervalSamples = 0x2000;
                wavInfo.streamSoundInfo.lastBlockSamples  = (uint)pcm8[0].Length % 0x2000;
                wavInfo.streamSoundInfo.lastBlockBytesize = wavInfo.streamSoundInfo.lastBlockPaddedBytesize = (uint)pcm8[0].Length % 0x2000;
                while (wavInfo.streamSoundInfo.lastBlockPaddedBytesize % 0x20 != 0)
                {
                    wavInfo.streamSoundInfo.lastBlockPaddedBytesize++;
                }
                wavInfo.streamSoundInfo.blockCount = (uint)pcm8[0].Length / 0x2000 + 1;
                break;

            //PCM16.
            case EncodingTypes.PCM16:
                wavInfo.streamSoundInfo.oneBlockSamples   = wavInfo.streamSoundInfo.seekInfoIntervalSamples = 0x1000;
                wavInfo.streamSoundInfo.lastBlockSamples  = (uint)pcm16[0].Length % 0x1000;
                wavInfo.streamSoundInfo.lastBlockBytesize = wavInfo.streamSoundInfo.lastBlockPaddedBytesize = (uint)pcm16[0].Length % 0x2000;
                while (wavInfo.streamSoundInfo.lastBlockPaddedBytesize % 0x20 != 0)
                {
                    wavInfo.streamSoundInfo.lastBlockPaddedBytesize++;
                }
                wavInfo.streamSoundInfo.blockCount = (uint)pcm16[0].Length / 0x1000 + 1;
                break;

            //DSP-ADPCM.
            case EncodingTypes.DSP_ADPCM:
                wavInfo.streamSoundInfo.oneBlockSamples   = wavInfo.streamSoundInfo.seekInfoIntervalSamples = 0x3800;
                wavInfo.streamSoundInfo.lastBlockSamples  = (uint)numSamples % 0x3800;
                wavInfo.streamSoundInfo.lastBlockBytesize = wavInfo.streamSoundInfo.lastBlockPaddedBytesize = (uint)dspAdpcm[0].Length % 0x2000;
                while (wavInfo.streamSoundInfo.lastBlockPaddedBytesize % 0x20 != 0)
                {
                    wavInfo.streamSoundInfo.lastBlockPaddedBytesize++;
                }
                wavInfo.streamSoundInfo.blockCount  = (uint)dspAdpcm[0].Length / 0x2000 + 1;
                wavInfo.streamSoundInfo.sampleCount = numSamples;
                break;
            }

            //Chunk the data first.
            List <byte>[][]  dspAdpcmBlocks = new List <byte> [wavInfo.channels.Count()][];
            List <Int16>[][] pcm16Blocks    = new List <Int16> [wavInfo.channels.Count()][];
            List <sbyte>[][] pcm8Blocks     = new List <sbyte> [wavInfo.channels.Count()][];
            for (int c = 0; c < wavInfo.channels.Count(); c++)
            {
                dspAdpcmBlocks[c] = new List <byte> [(int)wavInfo.streamSoundInfo.blockCount];
                pcm16Blocks[c]    = new List <Int16> [(int)wavInfo.streamSoundInfo.blockCount];
                pcm8Blocks[c]     = new List <sbyte> [(int)wavInfo.streamSoundInfo.blockCount];

                for (int i = 0; i < wavInfo.streamSoundInfo.blockCount; i++)
                {
                    pcm8Blocks[c][i]     = new List <sbyte>();
                    pcm16Blocks[c][i]    = new List <short>();
                    dspAdpcmBlocks[c][i] = new List <byte>();

                    //Normal block.
                    if (i != wavInfo.streamSoundInfo.blockCount - 1)
                    {
                        //Add to block.
                        switch (wavInfo.streamSoundInfo.encoding)
                        {
                        //PCM8.
                        case EncodingTypes.PCM8:
                            for (int j = i * 0x2000; j < i * 0x2000 + 0x2000; j++)
                            {
                                pcm8Blocks[c][i].Add(pcm8[c][j]);
                            }
                            break;

                        //PCM16.
                        case EncodingTypes.PCM16:
                            for (int j = i * 0x1000; j < i * 0x1000 + 0x1000; j++)
                            {
                                pcm16Blocks[c][i].Add(pcm16[c][j]);
                            }
                            break;

                        //DSP-ADPCM.
                        case EncodingTypes.DSP_ADPCM:
                            for (int j = i * 0x2000; j < i * 0x2000 + 0x2000; j++)
                            {
                                dspAdpcmBlocks[c][i].Add(dspAdpcm[c][j]);
                            }
                            break;
                        }
                    }

                    //Last block.
                    else
                    {
                        //Add to block.
                        switch (wavInfo.streamSoundInfo.encoding)
                        {
                        //PCM8.
                        case EncodingTypes.PCM8:
                            for (int j = i * 0x2000; j < pcm8[0].Length; j++)
                            {
                                pcm8Blocks[c][i].Add(pcm8[c][j]);
                            }
                            break;

                        //PCM16.
                        case EncodingTypes.PCM16:
                            for (int j = i * 0x1000; j < pcm16[0].Length; j++)
                            {
                                pcm16Blocks[c][i].Add(pcm16[c][j]);
                            }
                            break;

                        //DSP-ADPCM.
                        case EncodingTypes.DSP_ADPCM:
                            for (int j = i * 0x2000; j < dspAdpcm[0].Length; j++)
                            {
                                dspAdpcmBlocks[c][i].Add(dspAdpcm[c][j]);
                            }
                            break;
                        }
                    }
                }
            }

            //Write each block.
            for (int b = 0; b < wavInfo.streamSoundInfo.blockCount; b++)
            {
                //Write each channel.
                for (int c = 0; c < wavInfo.channels.Count(); c++)
                {
                    switch (wavInfo.streamSoundInfo.encoding)
                    {
                    //PCM8.
                    case EncodingTypes.PCM8:
                        foreach (sbyte s in pcm8Blocks[c][b].ToArray())
                        {
                            bw.Write(s);
                        }
                        break;

                    //PCM16.
                    case EncodingTypes.PCM16:
                        bw.Write(pcm16Blocks[c][b]);
                        break;

                    //DSP-ADPCM.
                    case EncodingTypes.DSP_ADPCM:
                        bw.Write(dspAdpcmBlocks[c][b].ToArray());
                        break;
                    }

                    //Write padding if last block.
                    if (b == wavInfo.streamSoundInfo.blockCount - 1)
                    {
                        while (bw.Position % 0x20 != 0)
                        {
                            bw.Write((byte)0);
                        }
                    }
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Load a file.
        /// </summary>
        /// <param name="b">The blue component.</param>
        public void Load(byte[] b)
        {
            //The reader.
            MemoryStream     src = new MemoryStream(b);
            BinaryDataReader br  = new BinaryDataReader(src);

            //Read the header.
            fileHeader = new FileHeader(ref br);

            //Read blocks.
            foreach (SizedReference s in fileHeader.blockOffsets)
            {
                if (s.offset != Reference.NULL_PTR)
                {
                    br.Position = s.offset;
                    switch (s.typeId)
                    {
                    //Info block.
                    case ReferenceTypes.STRM_Block_Info:
                        long basePos = br.Position + 8;
                        info = new InfoBlock()
                        {
                            magic               = br.ReadChars(4),
                            blockSize           = br.ReadUInt32(),
                            streamSoundInfoRef  = new Reference(ref br),
                            trackInfoTableRef   = new Reference(ref br),
                            channelInfoTableRef = new Reference(ref br),
                            streamSoundInfo     = null,
                            trackInfoRefTable   = null,
                            channelInfoRefTable = null,
                            tracks              = null,
                            channels            = null
                        };

                        //Stream sound info.
                        if (info.streamSoundInfoRef.typeId == ReferenceTypes.STRM_Info_StreamSound && info.streamSoundInfoRef.offset != Reference.NULL_PTR)
                        {
                            br.Position          = basePos + info.streamSoundInfoRef.offset;
                            info.streamSoundInfo = new StreamSoundInfo()
                            {
                                encoding                = br.ReadByte(),
                                isLoop                  = br.ReadBoolean(),
                                channelCount            = br.ReadByte(),
                                regionCount             = br.ReadByte(),
                                sampleRate              = br.ReadUInt32(),
                                loopStart               = br.ReadUInt32(),
                                sampleCount             = br.ReadUInt32(),
                                blockCount              = br.ReadUInt32(),
                                oneBlockBytesize        = br.ReadUInt32(),
                                oneBlockSamples         = br.ReadUInt32(),
                                lastBlockBytesize       = br.ReadUInt32(),
                                lastBlockSamples        = br.ReadUInt32(),
                                lastBlockPaddedBytesize = br.ReadUInt32(),
                                sizeOfSeekInfo          = br.ReadUInt32(),
                                seekInfoIntervalSamples = br.ReadUInt32(),
                                sampleDataOffset        = new Reference(ref br),
                                regionInfoBytesize      = 0x100,
                                padding                 = 0,
                                regionDataOffset        = new Reference(0, 0x18),
                                originalLoopStart       = 0,
                                originalLoopEnd         = 0,
                                secretInfo              = 0
                            };

                            if (fileHeader.vMajor >= regionInfo)
                            {
                                info.streamSoundInfo.regionInfoBytesize = br.ReadUInt16();
                                info.streamSoundInfo.padding            = br.ReadUInt16();
                                info.streamSoundInfo.regionDataOffset   = new Reference(ref br);
                            }

                            if (fileHeader.vMajor >= originalLoopInfo)
                            {
                                info.streamSoundInfo.originalLoopStart = br.ReadUInt32();
                                info.streamSoundInfo.originalLoopEnd   = br.ReadUInt32();
                            }

                            if (fileHeader.vMajor >= secretInfo)
                            {
                                info.streamSoundInfo.secretInfo = br.ReadUInt32();
                            }
                        }

                        //Track info.
                        if (info.trackInfoTableRef.typeId == ReferenceTypes.Tables + 1 && info.trackInfoTableRef.offset != Reference.NULL_PTR)
                        {
                            br.Position = basePos + info.trackInfoTableRef.offset;
                            long newPos = br.Position;
                            info.trackInfoRefTable = new ReferenceTable(ref br);

                            //Get tracks.
                            info.tracks = new List <TrackInfo>();
                            foreach (Reference r in info.trackInfoRefTable.references)
                            {
                                TrackInfo t = null;
                                if (r.typeId == ReferenceTypes.STRM_Info_Track && r.offset != Reference.NULL_PTR)
                                {
                                    br.Position = newPos + r.offset;
                                    t           = new TrackInfo()
                                    {
                                        volume       = br.ReadByte(),
                                        pan          = br.ReadByte(),
                                        span         = br.ReadByte(),
                                        surroundMode = br.ReadByte(),
                                        globalChannelIndexTableRef = new Reference(ref br),
                                        globalChannelIndexTable    = null
                                    };

                                    if (t.globalChannelIndexTableRef.offset != Reference.NULL_PTR)
                                    {
                                        br.Position = newPos + r.offset + t.globalChannelIndexTableRef.offset;
                                        t.globalChannelIndexTable         = new Table <byte>();
                                        t.globalChannelIndexTable.count   = br.ReadUInt32();
                                        t.globalChannelIndexTable.entries = new List <byte>();
                                        for (int i = 0; i < t.globalChannelIndexTable.count; i++)
                                        {
                                            t.globalChannelIndexTable.entries.Add(br.ReadByte());
                                        }
                                    }
                                }
                                info.tracks.Add(t);
                            }
                        }

                        //Channel info.
                        if (info.channelInfoTableRef.typeId == ReferenceTypes.Tables + 1 && info.channelInfoTableRef.offset != Reference.NULL_PTR)
                        {
                            br.Position = basePos + info.channelInfoTableRef.offset;
                            long newPos = br.Position;
                            info.channelInfoRefTable = new ReferenceTable(ref br);

                            //Get channels.
                            info.channels = new List <ChannelInfo>();
                            foreach (Reference r in info.channelInfoRefTable.references)
                            {
                                ChannelInfo c = null;
                                if (r.offset != Reference.NULL_PTR)
                                {
                                    br.Position = newPos + r.offset;
                                    c           = new ChannelInfo()
                                    {
                                        dspAdpcmInfoRef = new Reference(ref br),
                                        dspAdpcmInfo    = null
                                    };

                                    if (c.dspAdpcmInfoRef.offset != Reference.NULL_PTR)
                                    {
                                        br.Position    = newPos + r.offset + c.dspAdpcmInfoRef.offset;
                                        c.dspAdpcmInfo = new DspAdpcmInfo();
                                        c.dspAdpcmInfo = new DspAdpcmInfo()
                                        {
                                            coefs = new short[8][]
                                        };
                                        c.dspAdpcmInfo.coefs[0]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[1]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[2]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[3]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[4]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[5]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[6]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.coefs[7]        = br.ReadInt16s(2);
                                        c.dspAdpcmInfo.pred_scale      = br.ReadUInt16();
                                        c.dspAdpcmInfo.yn1             = br.ReadInt16();
                                        c.dspAdpcmInfo.yn2             = br.ReadInt16();
                                        c.dspAdpcmInfo.loop_pred_scale = br.ReadUInt16();
                                        c.dspAdpcmInfo.loop_yn1        = br.ReadInt16();
                                        c.dspAdpcmInfo.loop_yn2        = br.ReadInt16();
                                    }
                                }
                                info.channels.Add(c);
                            }
                        }

                        break;

                    //Data block.
                    case ReferenceTypes.STRM_Block_PrefetchData:
                        pdat       = new PdatBlock();
                        pdat.magic = br.ReadChars(4);
                        pdat.size  = br.ReadUInt32();
                        break;
                    }
                }
            }
        }