Beispiel #1
0
        private void LoadWaveBank(AudioEngine audioEngine, BinaryReader reader, bool streaming)
        {
            /* Until we finish the LoadWaveBank process, this WaveBank is NOT
             * ready to run. For us this doesn't really matter, but the game
             * could be loading WaveBanks asynchronously, so let's be careful.
             * -flibit
             */
            IsPrepared = false;

            INTERNAL_baseEngine = audioEngine;

            // Check the file header. Should be 'WBND'
            if (reader.ReadUInt32() != 0x444E4257)
            {
                throw new ArgumentException("WBND format not recognized!");
            }

            // Check the content version. Assuming XNA4 Refresh.
            if (reader.ReadUInt32() != AudioEngine.ContentVersion)
            {
                throw new ArgumentException("WBND Content version!");
            }

            // Check the tool version. Assuming XNA4 Refresh.
            if (reader.ReadUInt32() != 44)
            {
                throw new ArgumentException("WBND Tool version!");
            }

            // Obtain WaveBank chunk offsets/lengths
            uint[] offsets = new uint[5];
            uint[] lengths = new uint[5];
            for (int i = 0; i < 5; i += 1)
            {
                offsets[i] = reader.ReadUInt32();
                lengths[i] = reader.ReadUInt32();
            }

            // Seek to the first offset, obtain WaveBank info
            reader.BaseStream.Seek(offsets[0], SeekOrigin.Begin);

            // IsStreaming bool, unused
            reader.ReadUInt16();

            // WaveBank Flags
            ushort wavebankFlags = reader.ReadUInt16();
            // bool containsEntryNames =	(wavebankFlags & 0x0001) != 0;
            bool compact = (wavebankFlags & 0x0002) != 0;
            // bool syncDisabled =		(wavebankFlags & 0x0004) != 0;
            // bool containsSeekTables =	(wavebankFlags & 0x0008) != 0;

            // WaveBank Entry Count
            uint numEntries = reader.ReadUInt32();

            // WaveBank Name
            INTERNAL_name = System.Text.Encoding.UTF8.GetString(
                reader.ReadBytes(64), 0, 64
                ).Replace("\0", "");

            // WaveBank entry information
            uint metadataElementSize = reader.ReadUInt32();

            reader.ReadUInt32();             // nameElementSize
            uint alignment = reader.ReadUInt32();

            // Determine the generic play region offset
            uint playRegionOffset = offsets[4];

            if (playRegionOffset == 0)
            {
                playRegionOffset = offsets[1] + (numEntries * metadataElementSize);
            }

            // Entry format. Read early for Compact data
            uint entryFormat = 0;

            if (compact)
            {
                entryFormat = reader.ReadUInt32();
            }

            // Read in the wavedata
            INTERNAL_sounds = new SoundEffect[numEntries];
            if (streaming)
            {
                INTERNAL_soundStreamEntries = new SoundStreamEntry[numEntries];
            }
            uint curOffset = offsets[1];

            for (int curEntry = 0; curEntry < numEntries; curEntry += 1)
            {
                // Seek to the current entry
                reader.BaseStream.Seek(curOffset, SeekOrigin.Begin);

                // Entry Information
                uint entryPlayOffset = 0;
                uint entryPlayLength = 0;
                uint entryLoopOffset = 0;
                uint entryLoopLength = 0;

                // Obtain Entry Information
                if (compact)
                {
                    uint entryLength = reader.ReadUInt32();

                    entryPlayOffset =
                        (entryLength & ((1 << 21) - 1)) *
                        alignment;
                    entryPlayLength =
                        (entryLength >> 21) & ((1 << 11) - 1);

                    // FIXME: Deviation Length
                    reader.BaseStream.Seek(
                        curOffset + metadataElementSize,
                        SeekOrigin.Begin
                        );

                    if (curEntry == (numEntries - 1))
                    {
                        // Last track, last length.
                        entryLength = lengths[4];
                    }
                    else
                    {
                        entryLength = (
                            (
                                reader.ReadUInt32() &
                                ((1 << 21) - 1)
                            ) * alignment
                            );
                    }
                    entryPlayLength = entryLength - entryPlayOffset;
                }
                else
                {
                    if (metadataElementSize >= 4)
                    {
                        reader.ReadUInt32();                         // Flags/Duration, unused
                    }
                    if (metadataElementSize >= 8)
                    {
                        entryFormat = reader.ReadUInt32();
                    }
                    if (metadataElementSize >= 12)
                    {
                        entryPlayOffset = reader.ReadUInt32();
                    }
                    if (metadataElementSize >= 16)
                    {
                        entryPlayLength = reader.ReadUInt32();
                    }
                    if (metadataElementSize >= 20)
                    {
                        entryLoopOffset = reader.ReadUInt32();
                    }
                    if (metadataElementSize >= 24)
                    {
                        entryLoopLength = reader.ReadUInt32();
                    }
                    else
                    {
                        // FIXME: This is a bit hacky.
                        if (entryPlayLength != 0)
                        {
                            entryPlayLength = lengths[4];
                        }
                    }
                }

                // Update seek offsets
                curOffset       += metadataElementSize;
                entryPlayOffset += playRegionOffset;

                // Parse Format for Wavedata information
                uint entryCodec     = (entryFormat >> 0) & ((1 << 2) - 1);
                uint entryChannels  = (entryFormat >> 2) & ((1 << 3) - 1);
                uint entryFrequency = (entryFormat >> (2 + 3)) & ((1 << 18) - 1);
                uint entryAlignment = (entryFormat >> (2 + 3 + 18)) & ((1 << 8) - 1);
                uint entryBitDepth  = (entryFormat >> (2 + 3 + 18 + 8));

                if (streaming)
                {
                    INTERNAL_soundStreamEntries[curEntry] = new SoundStreamEntry(
                        entryPlayOffset,
                        entryPlayLength,
                        entryCodec,
                        entryFrequency,
                        entryChannels,
                        entryLoopOffset,
                        entryLoopLength,
                        entryAlignment,
                        entryBitDepth
                        );
                }
                else
                {
                    SoundStreamEntry filler = new SoundStreamEntry(
                        entryPlayOffset,
                        entryPlayLength,
                        entryCodec,
                        entryFrequency,
                        entryChannels,
                        entryLoopOffset,
                        entryLoopLength,
                        entryAlignment,
                        entryBitDepth
                        );
                    LoadWaveEntry(filler, (ushort)curEntry, reader);
                }
            }

            // Add this WaveBank to the AudioEngine Dictionary
            audioEngine.INTERNAL_addWaveBank(INTERNAL_name, this);

            // Finally.
            IsDisposed = false;
            IsPrepared = true;
        }
Beispiel #2
0
        private void LoadWaveBank(AudioEngine audioEngine, BinaryReader reader, bool streaming)
        {
            /* Until we finish the LoadWaveBank process, this WaveBank is NOT
             * ready to run. For us this doesn't really matter, but the game
             * could be loading WaveBanks asynchronously, so let's be careful.
             * -flibit
             */
            IsPrepared = false;

            INTERNAL_baseEngine = audioEngine;

            // Check the file header. Should be 'WBND'
            if (reader.ReadUInt32() != 0x444E4257)
            {
                throw new ArgumentException("WBND format not recognized!");
            }

            // Check the content version. Assuming XNA4 Refresh.
            if (reader.ReadUInt32() != AudioEngine.ContentVersion)
            {
                throw new ArgumentException("WBND Content version!");
            }

            // Check the tool version. Assuming XNA4 Refresh.
            if (reader.ReadUInt32() != 44)
            {
                throw new ArgumentException("WBND Tool version!");
            }

            // Obtain WaveBank chunk offsets/lengths
            uint[] offsets = new uint[5];
            uint[] lengths = new uint[5];
            for (int i = 0; i < 5; i += 1)
            {
                offsets[i] = reader.ReadUInt32();
                lengths[i] = reader.ReadUInt32();
            }

            // Seek to the first offset, obtain WaveBank info
            reader.BaseStream.Seek(offsets[0], SeekOrigin.Begin);

            // Unknown value, IsStreaming bool?
            reader.ReadUInt16();

            // WaveBank Flags
            ushort wavebankFlags = reader.ReadUInt16();
            // bool containsEntryNames =	(wavebankFlags & 0x00010000) != 0;
            bool compact =			(wavebankFlags & 0x00020000) != 0;
            // bool syncDisabled =		(wavebankFlags & 0x00040000) != 0;
            // bool containsSeekTables =	(wavebankFlags & 0x00080000) != 0;

            // WaveBank Entry Count
            uint numEntries = reader.ReadUInt32();

            // WaveBank Name
            INTERNAL_name = System.Text.Encoding.UTF8.GetString(
                reader.ReadBytes(64), 0, 64
            ).Replace("\0", "");

            // WaveBank entry information
            uint metadataElementSize = reader.ReadUInt32();
            reader.ReadUInt32(); // nameElementSize
            uint alignment = reader.ReadUInt32();

            // Determine the generic play region offset
            uint playRegionOffset = offsets[4];
            if (playRegionOffset == 0)
            {
                playRegionOffset = offsets[1] + (numEntries * metadataElementSize);
            }

            // Entry format. Read early for Compact data
            uint entryFormat = 0;
            if (compact)
            {
                entryFormat = reader.ReadUInt32();
            }

            // Read in the wavedata
            INTERNAL_sounds = new SoundEffect[numEntries];
            if (streaming)
            {
                INTERNAL_soundStreamEntries = new SoundStreamEntry[numEntries];
            }
            uint curOffset = offsets[1];
            for (int curEntry = 0; curEntry < numEntries; curEntry += 1)
            {
                // Seek to the current entry
                reader.BaseStream.Seek(curOffset, SeekOrigin.Begin);

                // Entry Information
                uint entryPlayOffset = 0;
                uint entryPlayLength = 0;
                uint entryLoopOffset = 0;
                uint entryLoopLength = 0;

                // Obtain Entry Information
                if (compact)
                {
                    uint entryLength = reader.ReadUInt32();

                    entryPlayOffset =
                        (entryLength & ((1 << 21) - 1)) *
                        alignment;
                    entryPlayLength =
                        (entryLength >> 21) & ((1 << 11) - 1);

                    // FIXME: Deviation Length
                    reader.BaseStream.Seek(
                        curOffset + metadataElementSize,
                        SeekOrigin.Begin
                    );

                    if (curEntry == (numEntries - 1))
                    {
                        // Last track, last length.
                        entryLength = lengths[4];
                    }
                    else
                    {
                        entryLength = (
                            (
                            reader.ReadUInt32() &
                            ((1 << 21) - 1)
                            ) * alignment
                        );
                    }
                    entryPlayLength = entryLength - entryPlayOffset;
                }
                else
                {
                    if (metadataElementSize >= 4)
                        reader.ReadUInt32(); // Flags/Duration, unused
                    if (metadataElementSize >= 8)
                        entryFormat = reader.ReadUInt32();
                    if (metadataElementSize >= 12)
                        entryPlayOffset = reader.ReadUInt32();
                    if (metadataElementSize >= 16)
                        entryPlayLength = reader.ReadUInt32();
                    if (metadataElementSize >= 20)
                        entryLoopOffset = reader.ReadUInt32();
                    if (metadataElementSize >= 24)
                        entryLoopLength = reader.ReadUInt32();
                    else
                    {
                        // FIXME: This is a bit hacky.
                        if (entryPlayLength != 0)
                        {
                            entryPlayLength = lengths[4];
                        }
                    }
                }

                // Update seek offsets
                curOffset += metadataElementSize;
                entryPlayOffset += playRegionOffset;

                // Parse Format for Wavedata information
                uint entryCodec =	(entryFormat >> 0)		& ((1 << 2) - 1);
                uint entryChannels =	(entryFormat >> 2)		& ((1 << 3) - 1);
                uint entryFrequency =	(entryFormat >> (2 + 3))	& ((1 << 18) - 1);
                uint entryAlignment =	(entryFormat >> (2 + 3 + 18))	& ((1 << 8) - 1);
                uint entryBitDepth =	(entryFormat >> (2 + 3 + 18 + 8));

                if (streaming)
                {
                    INTERNAL_soundStreamEntries[curEntry] = new SoundStreamEntry(
                        entryPlayOffset,
                        entryPlayLength,
                        entryCodec,
                        entryFrequency,
                        entryChannels,
                        entryLoopOffset,
                        entryLoopLength,
                        entryAlignment,
                        entryBitDepth
                    );
                }
                else
                {
                    SoundStreamEntry filler = new SoundStreamEntry(
                        entryPlayOffset,
                        entryPlayLength,
                        entryCodec,
                        entryFrequency,
                        entryChannels,
                        entryLoopOffset,
                        entryLoopLength,
                        entryAlignment,
                        entryBitDepth
                    );
                    LoadWaveEntry(filler, (ushort) curEntry, reader);
                }
            }

            // Add this WaveBank to the AudioEngine Dictionary
            audioEngine.INTERNAL_addWaveBank(INTERNAL_name, this);

            // Finally.
            IsDisposed = false;
            IsPrepared = true;
        }