Beispiel #1
0
        /// <param name="audioEngine">Instance of the AudioEngine to associate this wave bank with.</param>
        /// <param name="nonStreamingWaveBankFilename">Path to the .xwb file to load.</param>
        /// <remarks>This constructor immediately loads all wave data into memory at once.</remarks>
        public WaveBank(AudioEngine audioEngine, string nonStreamingWaveBankFilename)
        {
            if (audioEngine == null)
            {
                throw new ArgumentNullException("audioEngine");
            }
            if (string.IsNullOrEmpty(nonStreamingWaveBankFilename))
            {
                throw new ArgumentNullException("nonStreamingWaveBankFilename");
            }

            //XWB PARSING
            //Adapted from MonoXNA
            //Originally adaped from Luigi Auriemma's unxwb

            WaveBankHeader wavebankheader;
            WaveBankData   wavebankdata;
            WaveBankEntry  wavebankentry;

            wavebankdata.EntryNameElementSize = 0;
            wavebankdata.CompactFormat        = 0;
            wavebankdata.Alignment            = 0;
            wavebankdata.BuildTime            = 0;

            wavebankentry.Format            = 0;
            wavebankentry.PlayRegion.Length = 0;
            wavebankentry.PlayRegion.Offset = 0;

            int wavebank_offset = 0;

            BinaryReader reader = new BinaryReader(AudioEngine.OpenStream(nonStreamingWaveBankFilename));

            reader.ReadBytes(4);

            wavebankheader.Version = reader.ReadInt32();

            int last_segment = 4;

            //if (wavebankheader.Version == 1) goto WAVEBANKDATA;
            if (wavebankheader.Version <= 3)
            {
                last_segment = 3;
            }
            if (wavebankheader.Version >= 42)
            {
                reader.ReadInt32();                                  // skip HeaderVersion
            }
            wavebankheader.Segments = new Segment[5];

            for (int i = 0; i <= last_segment; i++)
            {
                wavebankheader.Segments[i].Offset = reader.ReadInt32();
                wavebankheader.Segments[i].Length = reader.ReadInt32();
            }

            reader.BaseStream.Seek(wavebankheader.Segments[0].Offset, SeekOrigin.Begin);

            //WAVEBANKDATA:

            wavebankdata.Flags      = reader.ReadInt32();
            wavebankdata.EntryCount = reader.ReadInt32();

            if ((wavebankheader.Version == 2) || (wavebankheader.Version == 3))
            {
                wavebankdata.BankName = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(16), 0, 16).Replace("\0", "");
            }
            else
            {
                wavebankdata.BankName = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(64), 0, 64).Replace("\0", "");
            }

            _bankName = wavebankdata.BankName;

            if (wavebankheader.Version == 1)
            {
                //wavebank_offset = (int)ftell(fd) - file_offset;
                wavebankdata.EntryMetaDataElementSize = 20;
            }
            else
            {
                wavebankdata.EntryMetaDataElementSize = reader.ReadInt32();
                wavebankdata.EntryNameElementSize     = reader.ReadInt32();
                wavebankdata.Alignment = reader.ReadInt32();
                wavebank_offset        = wavebankheader.Segments[1].Offset; //METADATASEGMENT
            }

            if ((wavebankdata.Flags & Flag_Compact) != 0)
            {
                reader.ReadInt32(); // compact_format
            }

            int playregion_offset = wavebankheader.Segments[last_segment].Offset;

            if (playregion_offset == 0)
            {
                playregion_offset =
                    wavebank_offset +
                    (wavebankdata.EntryCount * wavebankdata.EntryMetaDataElementSize);
            }

            int segidx_entry_name = 2;

            if (wavebankheader.Version >= 42)
            {
                segidx_entry_name = 3;
            }

            if ((wavebankheader.Segments[segidx_entry_name].Offset != 0) &&
                (wavebankheader.Segments[segidx_entry_name].Length != 0))
            {
                if (wavebankdata.EntryNameElementSize == -1)
                {
                    wavebankdata.EntryNameElementSize = 0;
                }
                byte[] entry_name = new byte[wavebankdata.EntryNameElementSize + 1];
                entry_name[wavebankdata.EntryNameElementSize] = 0;
            }

            _sounds = new SoundEffect[wavebankdata.EntryCount];

            for (int current_entry = 0; current_entry < wavebankdata.EntryCount; current_entry++)
            {
                reader.BaseStream.Seek(wavebank_offset, SeekOrigin.Begin);
                //SHOWFILEOFF;

                //memset(&wavebankentry, 0, sizeof(wavebankentry));
                wavebankentry.LoopRegion.Length = 0;
                wavebankentry.LoopRegion.Offset = 0;

                if ((wavebankdata.Flags & Flag_Compact) != 0)
                {
                    int len = reader.ReadInt32();
                    wavebankentry.Format            = wavebankdata.CompactFormat;
                    wavebankentry.PlayRegion.Offset = (len & ((1 << 21) - 1)) * wavebankdata.Alignment;
                    wavebankentry.PlayRegion.Length = (len >> 21) & ((1 << 11) - 1);

                    // workaround because I don't know how to handke the deviation length
                    reader.BaseStream.Seek(wavebank_offset + wavebankdata.EntryMetaDataElementSize, SeekOrigin.Begin);

                    //MYFSEEK(wavebank_offset + wavebankdata.dwEntryMetaDataElementSize); // seek to the next
                    if (current_entry == (wavebankdata.EntryCount - 1))
                    {              // the last track
                        len = wavebankheader.Segments[last_segment].Length;
                    }
                    else
                    {
                        len = ((reader.ReadInt32() & ((1 << 21) - 1)) * wavebankdata.Alignment);
                    }
                    wavebankentry.PlayRegion.Length =
                        len -                             // next offset
                        wavebankentry.PlayRegion.Offset;  // current offset
                    goto wavebank_handle;
                }

                if (wavebankheader.Version == 1)
                {
                    wavebankentry.Format            = reader.ReadInt32();
                    wavebankentry.PlayRegion.Offset = reader.ReadInt32();
                    wavebankentry.PlayRegion.Length = reader.ReadInt32();
                    wavebankentry.LoopRegion.Offset = reader.ReadInt32();
                    wavebankentry.LoopRegion.Length = reader.ReadInt32();
                }
                else
                {
                    if (wavebankdata.EntryMetaDataElementSize >= 4)
                    {
                        wavebankentry.FlagsAndDuration = reader.ReadInt32();
                    }
                    if (wavebankdata.EntryMetaDataElementSize >= 8)
                    {
                        wavebankentry.Format = reader.ReadInt32();
                    }
                    if (wavebankdata.EntryMetaDataElementSize >= 12)
                    {
                        wavebankentry.PlayRegion.Offset = reader.ReadInt32();
                    }
                    if (wavebankdata.EntryMetaDataElementSize >= 16)
                    {
                        wavebankentry.PlayRegion.Length = reader.ReadInt32();
                    }
                    if (wavebankdata.EntryMetaDataElementSize >= 20)
                    {
                        wavebankentry.LoopRegion.Offset = reader.ReadInt32();
                    }
                    if (wavebankdata.EntryMetaDataElementSize >= 24)
                    {
                        wavebankentry.LoopRegion.Length = reader.ReadInt32();
                    }
                }

                if (wavebankdata.EntryMetaDataElementSize < 24)
                {                              // work-around
                    if (wavebankentry.PlayRegion.Length != 0)
                    {
                        wavebankentry.PlayRegion.Length = wavebankheader.Segments[last_segment].Length;
                    }
                }// else if(wavebankdata.EntryMetaDataElementSize > sizeof(WaveBankEntry)) {    // skip unused fields
                //   MYFSEEK(wavebank_offset + wavebankdata.EntryMetaDataElementSize);
                //}

wavebank_handle:
                wavebank_offset += wavebankdata.EntryMetaDataElementSize;
                wavebankentry.PlayRegion.Offset += playregion_offset;

                // Parse WAVEBANKMINIWAVEFORMAT

                MiniFormatTag codec;
                int           chans;
                int           rate;
                int           align;
                //int bits;

                if (wavebankheader.Version == 1)
                {         // I'm not 100% sure if the following is correct
                    // version 1:
                    // 1 00000000 000101011000100010 0 001 0
                    // | |         |                 | |   |
                    // | |         |                 | |   wFormatTag
                    // | |         |                 | nChannels
                    // | |         |                 ???
                    // | |         nSamplesPerSec
                    // | wBlockAlign
                    // wBitsPerSample

                    codec = (MiniFormatTag)((wavebankentry.Format) & ((1 << 1) - 1));
                    chans = (wavebankentry.Format >> (1)) & ((1 << 3) - 1);
                    rate  = (wavebankentry.Format >> (1 + 3 + 1)) & ((1 << 18) - 1);
                    align = (wavebankentry.Format >> (1 + 3 + 1 + 18)) & ((1 << 8) - 1);
                    //bits = (wavebankentry.Format >> (1 + 3 + 1 + 18 + 8)) & ((1 << 1) - 1);

                    /*} else if(wavebankheader.dwVersion == 23) { // I'm not 100% sure if the following is correct
                     *  // version 23:
                     *  // 1000000000 001011101110000000 001 1
                     *  // | |        |                  |   |
                     *  // | |        |                  |   ???
                     *  // | |        |                  nChannels?
                     *  // | |        nSamplesPerSec
                     *  // | ???
                     *  // !!!UNKNOWN FORMAT!!!
                     *
                     *  //codec = -1;
                     *  //chans = (wavebankentry.Format >>  1) & ((1 <<  3) - 1);
                     *  //rate  = (wavebankentry.Format >>  4) & ((1 << 18) - 1);
                     *  //bits  = (wavebankentry.Format >> 31) & ((1 <<  1) - 1);
                     *  codec = (wavebankentry.Format                    ) & ((1 <<  1) - 1);
                     *  chans = (wavebankentry.Format >> (1)             ) & ((1 <<  3) - 1);
                     *  rate  = (wavebankentry.Format >> (1 + 3)         ) & ((1 << 18) - 1);
                     *  align = (wavebankentry.Format >> (1 + 3 + 18)    ) & ((1 <<  9) - 1);
                     *  bits  = (wavebankentry.Format >> (1 + 3 + 18 + 9)) & ((1 <<  1) - 1); */
                }
                else
                {
                    // 0 00000000 000111110100000000 010 01
                    // | |        |                  |   |
                    // | |        |                  |   wFormatTag
                    // | |        |                  nChannels
                    // | |        nSamplesPerSec
                    // | wBlockAlign
                    // wBitsPerSample

                    codec = (MiniFormatTag)((wavebankentry.Format) & ((1 << 2) - 1));
                    chans = (wavebankentry.Format >> (2)) & ((1 << 3) - 1);
                    rate  = (wavebankentry.Format >> (2 + 3)) & ((1 << 18) - 1);
                    align = (wavebankentry.Format >> (2 + 3 + 18)) & ((1 << 8) - 1);
                    //bits = (wavebankentry.Format >> (2 + 3 + 18 + 8)) & ((1 << 1) - 1);
                }

                reader.BaseStream.Seek(wavebankentry.PlayRegion.Offset, SeekOrigin.Begin);
                byte[] audiodata = reader.ReadBytes(wavebankentry.PlayRegion.Length);

                // Call the special constuctor on SoundEffect to sort it out.
                _sounds[current_entry] = new SoundEffect(codec, audiodata, chans, rate, align, wavebankentry.LoopRegion.Offset, wavebankentry.LoopRegion.Length);
            }

            audioEngine.Wavebanks[_bankName] = this;

            IsPrepared = true;
        }
Beispiel #2
0
        /// <param name="audioEngine">AudioEngine that will be associated with this sound bank.</param>
        /// <param name="fileName">Path to a .xsb SoundBank file.</param>
        public SoundBank(AudioEngine audioEngine, string fileName)
        {
            if (audioEngine == null)
            {
                throw new ArgumentNullException("audioEngine");
            }
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException("fileName");
            }

            _audioengine = audioEngine;

            using (var stream = AudioEngine.OpenStream(fileName))
                using (var reader = new BinaryReader(stream))
                {
                    // Thanks to Liandril for "xactxtract" for some of the offsets.

                    uint magic = reader.ReadUInt32();
                    if (magic != 0x4B424453) //"SDBK"
                    {
                        throw new Exception("Bad soundbank format");
                    }

                    reader.ReadUInt16(); // toolVersion

                    uint formatVersion = reader.ReadUInt16();
                    if (formatVersion != 43)
                    {
                        Debug.WriteLine("Warning: SoundBank format {0} not supported.", formatVersion);
                    }

                    reader.ReadUInt16(); // crc, TODO: Verify crc (FCS16)

                    reader.ReadUInt32(); // lastModifiedLow
                    reader.ReadUInt32(); // lastModifiedHigh
                    reader.ReadByte();   // platform ???

                    uint numSimpleCues  = reader.ReadUInt16();
                    uint numComplexCues = reader.ReadUInt16();
                    reader.ReadUInt16(); //unkn
                    reader.ReadUInt16(); // numTotalCues
                    uint numWaveBanks = reader.ReadByte();
                    reader.ReadUInt16(); // numSounds
                    uint cueNameTableLen = reader.ReadUInt16();
                    reader.ReadUInt16(); //unkn

                    uint simpleCuesOffset  = reader.ReadUInt32();
                    uint complexCuesOffset = reader.ReadUInt32(); //unkn
                    uint cueNamesOffset    = reader.ReadUInt32();
                    reader.ReadUInt32();                          //unkn
                    reader.ReadUInt32();                          // variationTablesOffset
                    reader.ReadUInt32();                          //unkn
                    uint waveBankNameTableOffset = reader.ReadUInt32();
                    reader.ReadUInt32();                          // cueNameHashTableOffset
                    reader.ReadUInt32();                          // cueNameHashValsOffset
                    reader.ReadUInt32();                          // soundsOffset

                    //name = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64),0,64).Replace("\0","");

                    //parse wave bank name table
                    stream.Seek(waveBankNameTableOffset, SeekOrigin.Begin);
                    _waveBanks     = new WaveBank[numWaveBanks];
                    _waveBankNames = new string[numWaveBanks];
                    for (int i = 0; i < numWaveBanks; i++)
                    {
                        _waveBankNames[i] = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(64), 0, 64).Replace("\0", "");
                    }

                    //parse cue name table
                    stream.Seek(cueNamesOffset, SeekOrigin.Begin);
                    string[] cueNames = System.Text.Encoding.UTF8.GetString(reader.ReadBytes((int)cueNameTableLen), 0, (int)cueNameTableLen).Split('\0');

                    // Simple cues
                    if (numSimpleCues > 0)
                    {
                        stream.Seek(simpleCuesOffset, SeekOrigin.Begin);
                        for (int i = 0; i < numSimpleCues; i++)
                        {
                            reader.ReadByte(); // flags
                            uint soundOffset = reader.ReadUInt32();

                            var oldPosition = stream.Position;
                            stream.Seek(soundOffset, SeekOrigin.Begin);
                            XactSound sound = new XactSound(audioEngine, this, reader);
                            stream.Seek(oldPosition, SeekOrigin.Begin);

                            _sounds.Add(cueNames [i], new XactSound [] { sound });
                            _probabilities.Add(cueNames [i], defaultProbability);
                        }
                    }

                    // Complex cues
                    if (numComplexCues > 0)
                    {
                        stream.Seek(complexCuesOffset, SeekOrigin.Begin);
                        for (int i = 0; i < numComplexCues; i++)
                        {
                            byte flags = reader.ReadByte();
                            if (((flags >> 2) & 1) != 0)
                            {
                                uint soundOffset = reader.ReadUInt32();
                                reader.ReadUInt32(); //unkn

                                var oldPosition = stream.Position;
                                stream.Seek(soundOffset, SeekOrigin.Begin);
                                XactSound sound = new XactSound(audioEngine, this, reader);
                                stream.Seek(oldPosition, SeekOrigin.Begin);

                                _sounds.Add(cueNames [numSimpleCues + i], new XactSound [] { sound });
                                _probabilities.Add(cueNames [numSimpleCues + i], defaultProbability);
                            }
                            else
                            {
                                uint variationTableOffset = reader.ReadUInt32();
                                reader.ReadUInt32(); // transitionTableOffset

                                //parse variation table
                                long savepos = stream.Position;
                                stream.Seek(variationTableOffset, SeekOrigin.Begin);

                                uint numEntries     = reader.ReadUInt16();
                                uint variationflags = reader.ReadUInt16();
                                reader.ReadByte();
                                reader.ReadUInt16();
                                reader.ReadByte();

                                XactSound[] cueSounds = new XactSound[numEntries];
                                float[]     probs     = new float[numEntries];

                                uint tableType = (variationflags >> 3) & 0x7;
                                for (int j = 0; j < numEntries; j++)
                                {
                                    switch (tableType)
                                    {
                                    case 0: //Wave
                                    {
                                        int trackIndex    = reader.ReadUInt16();
                                        int waveBankIndex = reader.ReadByte();
                                        reader.ReadByte();     // weightMin
                                        reader.ReadByte();     // weightMax

                                        cueSounds[j] = new XactSound(this, waveBankIndex, trackIndex);
                                        break;
                                    }

                                    case 1:
                                    {
                                        uint soundOffset = reader.ReadUInt32();
                                        reader.ReadByte();     // weightMin
                                        reader.ReadByte();     // weightMax

                                        var oldPosition = stream.Position;
                                        stream.Seek(soundOffset, SeekOrigin.Begin);
                                        cueSounds[j] = new XactSound(audioEngine, this, reader);
                                        stream.Seek(oldPosition, SeekOrigin.Begin);
                                        break;
                                    }

                                    case 3:
                                    {
                                        uint soundOffset = reader.ReadUInt32();
                                        reader.ReadSingle();     // weightMin
                                        reader.ReadSingle();     // weightMax
                                        reader.ReadUInt32();     // flags

                                        var oldPosition = stream.Position;
                                        stream.Seek(soundOffset, SeekOrigin.Begin);
                                        cueSounds[j] = new XactSound(audioEngine, this, reader);
                                        stream.Seek(oldPosition, SeekOrigin.Begin);
                                        break;
                                    }

                                    case 4: //CompactWave
                                    {
                                        int trackIndex    = reader.ReadUInt16();
                                        int waveBankIndex = reader.ReadByte();
                                        cueSounds[j] = new XactSound(this, waveBankIndex, trackIndex);
                                        break;
                                    }

                                    default:
                                        throw new NotSupportedException();
                                    }
                                }

                                stream.Seek(savepos, SeekOrigin.Begin);

                                _sounds.Add(cueNames [numSimpleCues + i], cueSounds);
                                _probabilities.Add(cueNames [numSimpleCues + i], probs);
                            }

                            // Instance limiting
                            reader.ReadByte();   //instanceLimit
                            reader.ReadUInt16(); //fadeInSec, divide by 1000.0f
                            reader.ReadUInt16(); //fadeOutSec, divide by 1000.0f
                            reader.ReadByte();   //instanceFlags
                        }
                    }
                }
        }
        private WaveBank(AudioEngine audioEngine, string waveBankFilename, bool streaming, int offset, int packetsize)
        {
            if (audioEngine == null)
            {
                throw new ArgumentNullException("audioEngine");
            }
            if (string.IsNullOrEmpty(waveBankFilename))
            {
                throw new ArgumentNullException("nonStreamingWaveBankFilename");
            }

            // Is this a streaming wavebank?
            if (streaming)
            {
                if (offset != 0)
                {
                    throw new ArgumentException("We only support a zero offset in streaming banks.", "offset");
                }
                if (packetsize < 2)
                {
                    throw new ArgumentException("The packet size must be greater than 2.", "packetsize");
                }

                _streaming  = true;
                _offset     = offset;
                _packetSize = packetsize;
            }

            //XWB PARSING
            //Adapted from MonoXNA
            //Originally adaped from Luigi Auriemma's unxwb

            WaveBankHeader wavebankheader;
            WaveBankData   wavebankdata;

            wavebankdata.EntryNameElementSize = 0;
            wavebankdata.CompactFormat        = 0;
            wavebankdata.Alignment            = 0;
            wavebankdata.BuildTime            = 0;

            int wavebank_offset = 0;

            _waveBankFileName = waveBankFilename;

            BinaryReader reader = new BinaryReader(AudioEngine.OpenStream(waveBankFilename));

            reader.ReadBytes(4);

            _version = wavebankheader.Version = reader.ReadInt32();

            int last_segment = 4;

            //if (wavebankheader.Version == 1) goto WAVEBANKDATA;
            if (wavebankheader.Version <= 3)
            {
                last_segment = 3;
            }
            if (wavebankheader.Version >= 42)
            {
                reader.ReadInt32();                                  // skip HeaderVersion
            }
            wavebankheader.Segments = new Segment[5];

            for (int i = 0; i <= last_segment; i++)
            {
                wavebankheader.Segments[i].Offset = reader.ReadInt32();
                wavebankheader.Segments[i].Length = reader.ReadInt32();
            }

            reader.BaseStream.Seek(wavebankheader.Segments[0].Offset, SeekOrigin.Begin);

            //WAVEBANKDATA:

            wavebankdata.Flags      = reader.ReadInt32();
            wavebankdata.EntryCount = reader.ReadInt32();

            if ((wavebankheader.Version == 2) || (wavebankheader.Version == 3))
            {
                wavebankdata.BankName = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(16), 0, 16).Replace("\0", "");
            }
            else
            {
                wavebankdata.BankName = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(64), 0, 64).Replace("\0", "");
            }

            _bankName = wavebankdata.BankName;

            if (wavebankheader.Version == 1)
            {
                //wavebank_offset = (int)ftell(fd) - file_offset;
                wavebankdata.EntryMetaDataElementSize = 20;
            }
            else
            {
                wavebankdata.EntryMetaDataElementSize = reader.ReadInt32();
                wavebankdata.EntryNameElementSize     = reader.ReadInt32();
                wavebankdata.Alignment = reader.ReadInt32();
                wavebank_offset        = wavebankheader.Segments[1].Offset; //METADATASEGMENT
            }

            if ((wavebankdata.Flags & Flag_Compact) != 0)
            {
                reader.ReadInt32(); // compact_format
            }

            _playRegionOffset = wavebankheader.Segments[last_segment].Offset;
            if (_playRegionOffset == 0)
            {
                _playRegionOffset =
                    wavebank_offset +
                    (wavebankdata.EntryCount * wavebankdata.EntryMetaDataElementSize);
            }

            int segidx_entry_name = 2;

            if (wavebankheader.Version >= 42)
            {
                segidx_entry_name = 3;
            }

            if ((wavebankheader.Segments[segidx_entry_name].Offset != 0) &&
                (wavebankheader.Segments[segidx_entry_name].Length != 0))
            {
                if (wavebankdata.EntryNameElementSize == -1)
                {
                    wavebankdata.EntryNameElementSize = 0;
                }
                byte[] entry_name = new byte[wavebankdata.EntryNameElementSize + 1];
                entry_name[wavebankdata.EntryNameElementSize] = 0;
            }

            _sounds  = new SoundEffect[wavebankdata.EntryCount];
            _streams = new StreamInfo[wavebankdata.EntryCount];

            reader.BaseStream.Seek(wavebank_offset, SeekOrigin.Begin);

            // The compact format requires us to load stuff differently.
            var isCompactFormat = (wavebankdata.Flags & Flag_Compact) != 0;

            if (isCompactFormat)
            {
                // Load the sound data offset table from disk.
                for (var i = 0; i < wavebankdata.EntryCount; i++)
                {
                    var len = reader.ReadInt32();
                    _streams[i].Format     = wavebankdata.CompactFormat;
                    _streams[i].FileOffset = (len & ((1 << 21) - 1)) * wavebankdata.Alignment;
                }

                // Now figure out the sound data lengths.
                for (var i = 0; i < wavebankdata.EntryCount; i++)
                {
                    int nextOffset;
                    if (i == (wavebankdata.EntryCount - 1))
                    {
                        nextOffset = wavebankheader.Segments[last_segment].Length;
                    }
                    else
                    {
                        nextOffset = _streams[i + 1].FileOffset;
                    }

                    // The next and current offsets used to calculate the length.
                    _streams[i].FileLength = nextOffset - _streams[i].FileOffset;
                }
            }
            else
            {
                for (var i = 0; i < wavebankdata.EntryCount; i++)
                {
                    var info = new StreamInfo();
                    if (wavebankheader.Version == 1)
                    {
                        info.Format     = reader.ReadInt32();
                        info.FileOffset = reader.ReadInt32();
                        info.FileLength = reader.ReadInt32();
                        info.LoopStart  = reader.ReadInt32();
                        info.LoopLength = reader.ReadInt32();
                    }
                    else
                    {
                        var flagsAndDuration = reader.ReadInt32(); // Unused

                        if (wavebankdata.EntryMetaDataElementSize >= 8)
                        {
                            info.Format = reader.ReadInt32();
                        }
                        if (wavebankdata.EntryMetaDataElementSize >= 12)
                        {
                            info.FileOffset = reader.ReadInt32();
                        }
                        if (wavebankdata.EntryMetaDataElementSize >= 16)
                        {
                            info.FileLength = reader.ReadInt32();
                        }
                        if (wavebankdata.EntryMetaDataElementSize >= 20)
                        {
                            info.LoopStart = reader.ReadInt32();
                        }
                        if (wavebankdata.EntryMetaDataElementSize >= 24)
                        {
                            info.LoopLength = reader.ReadInt32();
                        }
                    }

                    // TODO: What is this doing?
                    if (wavebankdata.EntryMetaDataElementSize < 24)
                    {
                        if (info.FileLength != 0)
                        {
                            info.FileLength = wavebankheader.Segments[last_segment].Length;
                        }
                    }

                    _streams[i] = info;
                }
            }

            // If this isn't a streaming wavebank then load all the sounds now.
            if (!_streaming)
            {
                for (var i = 0; i < _streams.Length; i++)
                {
                    var info = _streams[i];

                    // Read the data.
                    reader.BaseStream.Seek(info.FileOffset + _playRegionOffset, SeekOrigin.Begin);
                    var audiodata = reader.ReadBytes(info.FileLength);

                    // Decode the format information.
                    MiniFormatTag codec;
                    int           channels, rate, alignment;
                    DecodeFormat(info.Format, out codec, out channels, out rate, out alignment);

                    // Call the special constuctor on SoundEffect to sort it out.
                    _sounds[i] = new SoundEffect(codec, audiodata, channels, rate, alignment, info.LoopStart, info.LoopLength);
                }

                _streams = null;
            }

            audioEngine.Wavebanks[_bankName] = this;

            IsPrepared = true;
        }