Example #1
0
 internal void Prepare()
 {
     IsDisposed    = false;
     IsCreated     = false;
     IsPrepared    = true;
     _currentSound = null;
 }
Example #2
0
 internal Cue(AudioEngine engine, string cuename, XactSound sound)
 {
     _engine    = engine;
     Name       = cuename;
     _sounds    = new XactSound[1];
     _sounds[0] = sound;
     _probs     = new float[1];
     _probs[0]  = 1f;
     _variables = engine.CreateCueVariables();
 }
Example #3
0
        /// <summary>
        /// Requests playback of a prepared or preparing <see cref="Cue"/>.
        /// </summary>
        public void Play()
        {
            lock (_engine.UpdateLock)
            {
                if (!_engine.ActiveCues.Contains(this))
                {
                    _engine.ActiveCues.Add(this);
                }

                //TODO: Probabilities
                var index = XactHelpers.Random.Next(_sounds.Length);
                _currentSound = _sounds[index];

                var volume = UpdateRpcCurves();

                _currentSound.Play(volume, _engine);
            }

            _played    = true;
            IsPrepared = false;
        }
Example #4
0
 internal void AddSound(XactSound sound)
 {
     _sounds.Add(sound);
 }
Example #5
0
        /// <param name="audioEngine">The engine that will be associated with this sound bank.</param>
        /// <param name="fileName">Path to a .xsb sound bank file.</param>
        public SoundBank(AudioEngine audioEngine, string fileName)
        {
            _audioengine = audioEngine ?? throw new ArgumentNullException(nameof(audioEngine));

            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(nameof(fileName));
            }

            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

                    //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)).Replace("\0", "", StringComparison.Ordinal);
                    }

                    //parse cue name table
                    stream.Seek(cueNamesOffset, SeekOrigin.Begin);
                    string[] cueNames = System.Text.Encoding.UTF8
                                        .GetString(reader.ReadBytes((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);
                            var sound = new XactSound(audioEngine, this, reader);
                            stream.Seek(oldPosition, SeekOrigin.Begin);

                            _entries.Add(
                                cueNames[i],
                                new XactCueEntry(new XactSound[] { sound }, _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);
                                var sound = new XactSound(audioEngine, this, reader);
                                stream.Seek(oldPosition, SeekOrigin.Begin);

                                _entries.Add(
                                    cueNames[numSimpleCues + i],
                                    new XactCueEntry(new XactSound[] { sound }, _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();

                                var cueSounds = new XactSound[numEntries];
                                var 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);

                                _entries.Add(
                                    cueNames[numSimpleCues + i], new XactCueEntry(cueSounds, probs));
                            }

                            // Instance limiting
                            reader.ReadByte();   //instanceLimit
                            reader.ReadUInt16(); //fadeInSec, divide by 1000f
                            reader.ReadUInt16(); //fadeOutSec, divide by 1000f
                            reader.ReadByte();   //instanceFlags
                        }
                    }
                }
        }