internal void Prepare() { IsDisposed = false; IsCreated = false; IsPrepared = true; _curSound = null; }
internal Cue(string cuename, XactSound[] _sounds, float[] _probs) { this.name = cuename; this.sounds = _sounds; this.probs = _probs; this.variationRand = new Random(); }
public void Play() { this.curSound = this.sounds[this.variationRand.Next(this.sounds.Length)]; this.curSound.Volume = this.volume; this.curSound.Play(); this.paused = false; }
internal Cue(string cuename, XactSound[] _sounds, float[] _probs) { name = cuename; sounds = _sounds; probs = _probs; variationRand = new Random(); }
public void Play() { //TODO: Probabilities curSound = sounds[variationRand.Next(sounds.Length)]; curSound.Volume = volume; curSound.Play(); }
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] = 1.0f; }
internal Cue(AudioEngine engine, string cuename, XactSound sound) { _engine = engine; _sounds = new XactSound[1]; _sounds[0] = sound; _probs = new float[1]; _probs[0] = 1.0f; _variables = engine.CreateCueVariables(); }
internal Cue(AudioEngine engine, string cuename, XactSound sound) { this.engine = engine; this.name = cuename; this.sounds = new XactSound[1]; this.sounds[0] = sound; this.probs = new float[1]; this.probs[0] = 1f; this.variationRand = new Random(); }
internal Cue(AudioEngine engine, string cuename, XactSound sound) { this.engine = engine; name = cuename; sounds = new XactSound[1]; sounds[0] = sound; probs = new float[1]; probs[0] = 1.0f; }
internal Cue(string cuename, XactSound sound) { name = cuename; sounds = new XactSound[1]; sounds[0] = sound; probs = new float[1]; probs[0] = 1.0f; variationRand = new Random(); }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { if (!engine._activeCues.Contains(this)) { engine._activeCues.Add(this); } //TODO: Probabilities var index = XactHelpers.Random.Next(sounds.Length); curSound = sounds[index]; curSound.Volume = volume; curSound.Play(); }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { if (!_engine._activeCues.Contains(this)) { _engine._activeCues.Add(this); } //TODO: Probabilities var index = XactHelpers.Random.Next(_sounds.Length); _curSound = _sounds[index]; _curSound.SetCueVolume(_volume); _curSound.Play(); }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { if (!_engine.ActiveCues.Contains(this)) { _engine.ActiveCues.Add(this); } //TODO: Probabilities var index = XactHelpers.Random.Next(_sounds.Length); _curSound = _sounds[index]; _curSound.Play(1.0f, _engine); _played = true; IsPrepared = false; }
public void Play() { //TODO: Probabilities curSound = sounds[variationRand.Next(sounds.Length)]; // There may not have been a sound when we first set volume. curSound.Volume = volume * rpcVolume; if (positionalAudio) { curSound.PlayPositional(listener, emitter); } else { curSound.Play(); } }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { lock (_engine.UpdateLock) { if (!_engine.ActiveCues.Contains(this)) { _engine.ActiveCues.Add(this); } //TODO: Probabilities var index = XactHelpers.Random.Next(_sounds.Length); _curSound = _sounds[index]; var volume = UpdateRpcCurves(); _curSound.Play(volume, _engine); } _played = true; IsPrepared = false; }
//Defer loading because some programs load soundbanks before wavebanks private void Load () { #if !ANDROID using (FileStream soundbankstream = new FileStream (filename, FileMode.Open)) { #else using (var fileStream = Game.Activity.Assets.Open(filename)) { MemoryStream soundbankstream = new MemoryStream(); fileStream.CopyTo(soundbankstream); soundbankstream.Position = 0; #endif using(BinaryReader soundbankreader = new BinaryReader (soundbankstream)) { //Parse the SoundBank. //Thanks to Liandril for "xactxtract" for some of the offsets uint magic = soundbankreader.ReadUInt32 (); if (magic != 0x4B424453) { //"SDBK" throw new Exception ("Bad soundbank format"); } uint toolVersion = soundbankreader.ReadUInt16 (); uint formatVersion = soundbankreader.ReadUInt16 (); if (formatVersion != 46) { #if DEBUG Console.WriteLine ("Warning: SoundBank format not supported"); #endif } uint crc = soundbankreader.ReadUInt16 (); //TODO: Verify crc (FCS16) uint lastModifiedLow = soundbankreader.ReadUInt32 (); uint lastModifiedHigh = soundbankreader.ReadUInt32 (); uint platform = soundbankreader.ReadByte(); //??? uint numSimpleCues = soundbankreader.ReadUInt16 (); uint numComplexCues = soundbankreader.ReadUInt16 (); soundbankreader.ReadUInt16 (); //unkn uint numTotalCues = soundbankreader.ReadUInt16 (); uint numWaveBanks = soundbankreader.ReadByte (); uint numSounds = soundbankreader.ReadUInt16 (); uint cueNameTableLen = soundbankreader.ReadUInt16 (); soundbankreader.ReadUInt16 (); //unkn uint simpleCuesOffset = soundbankreader.ReadUInt32 (); uint complexCuesOffset = soundbankreader.ReadUInt32 (); //unkn uint cueNamesOffset = soundbankreader.ReadUInt32 (); soundbankreader.ReadUInt32 (); //unkn uint variationTablesOffset = soundbankreader.ReadUInt32 (); soundbankreader.ReadUInt32 (); //unkn uint waveBankNameTableOffset = soundbankreader.ReadUInt32 (); uint cueNameHashTableOffset = soundbankreader.ReadUInt32 (); uint cueNameHashValsOffset = soundbankreader.ReadUInt32 (); uint soundsOffset = soundbankreader.ReadUInt32 (); name = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0",""); //parse wave bank name table soundbankstream.Seek (waveBankNameTableOffset, SeekOrigin.Begin); waveBanks = new WaveBank[numWaveBanks]; for (int i=0; i<numWaveBanks; i++) { string bankname = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0",""); waveBanks[i] = audioengine.Wavebanks[bankname]; } //parse cue name table soundbankstream.Seek (cueNamesOffset, SeekOrigin.Begin); string[] cueNames = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes((int)cueNameTableLen)).Split('\0'); soundbankstream.Seek (simpleCuesOffset, SeekOrigin.Begin); for (int i=0; i<numSimpleCues; i++) { byte flags = soundbankreader.ReadByte (); uint soundOffset = soundbankreader.ReadUInt32 (); XactSound sound = new XactSound(this, soundbankreader, soundOffset); Cue cue = new Cue(audioengine, cueNames[i], sound); cues.Add(cue.Name, cue); } soundbankstream.Seek (complexCuesOffset, SeekOrigin.Begin); for (int i=0; i<numComplexCues; i++) { Cue cue; byte flags = soundbankreader.ReadByte (); if (((flags >> 2) & 1) != 0) { //not sure :/ uint soundOffset = soundbankreader.ReadUInt32 (); soundbankreader.ReadUInt32 (); //unkn XactSound sound = new XactSound(this, soundbankreader, soundOffset); cue = new Cue(audioengine, cueNames[numSimpleCues+i], sound); } else { uint variationTableOffset = soundbankreader.ReadUInt32 (); uint transitionTableOffset = soundbankreader.ReadUInt32 (); //parse variation table long savepos = soundbankstream.Position; soundbankstream.Seek (variationTableOffset, SeekOrigin.Begin); uint numEntries = soundbankreader.ReadUInt16 (); uint variationflags = soundbankreader.ReadUInt16 (); soundbankreader.ReadByte (); soundbankreader.ReadUInt16 (); soundbankreader.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 { uint trackIndex = soundbankreader.ReadUInt16 (); byte waveBankIndex = soundbankreader.ReadByte (); byte weightMin = soundbankreader.ReadByte (); byte weightMax = soundbankreader.ReadByte (); cueSounds[j] = new XactSound(this.GetWave(waveBankIndex, trackIndex)); break; } case 1: { uint soundOffset = soundbankreader.ReadUInt32 (); byte weightMin = soundbankreader.ReadByte (); byte weightMax = soundbankreader.ReadByte (); cueSounds[j] = new XactSound(this, soundbankreader, soundOffset); break; } case 4: //CompactWave { uint trackIndex = soundbankreader.ReadUInt16 (); byte waveBankIndex = soundbankreader.ReadByte (); cueSounds[j] = new XactSound(this.GetWave(waveBankIndex, trackIndex)); break; } default: throw new NotImplementedException(); } } soundbankstream.Seek (savepos, SeekOrigin.Begin); cue = new Cue(cueNames[numSimpleCues+i], cueSounds, probs); } //Instance Limit soundbankreader.ReadUInt32 (); soundbankreader.ReadByte (); soundbankreader.ReadByte (); cues.Add(cue.Name, cue); } } } loaded = true; }
internal void AddSound(XactSound sound) { sounds.Add(sound); }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { if (!_engine._activeCues.Contains(this)) _engine._activeCues.Add(this); //TODO: Probabilities var index = XactHelpers.Random.Next(_sounds.Length); _curSound = _sounds[index]; _curSound.SetCueVolume(_volume); _curSound.Play(); }
internal Cue(AudioEngine engine, string cuename, XactSound[] sounds, float[] probs) { _engine = engine; _name = cuename; _sounds = sounds; _probs = probs; }
internal Cue(AudioEngine engine, string cuename, XactSound[] _sounds, float[] _probs) { this.engine = engine; name = cuename; sounds = _sounds; probs = _probs; }
private void Load() { FileStream fileStream = new FileStream(this.filename, FileMode.Open); BinaryReader soundReader = new BinaryReader((Stream) fileStream); if ((int) soundReader.ReadUInt32() != 1262634067) throw new Exception("Bad soundbank format"); uint num1 = (uint) soundReader.ReadUInt16(); if ((int) soundReader.ReadUInt16() == 46) ; uint num2 = (uint) soundReader.ReadUInt16(); soundReader.ReadUInt32(); soundReader.ReadUInt32(); uint num3 = (uint) soundReader.ReadByte(); uint num4 = (uint) soundReader.ReadUInt16(); uint num5 = (uint) soundReader.ReadUInt16(); int num6 = (int) soundReader.ReadUInt16(); uint num7 = (uint) soundReader.ReadUInt16(); uint num8 = (uint) soundReader.ReadByte(); uint num9 = (uint) soundReader.ReadUInt16(); uint num10 = (uint) soundReader.ReadUInt16(); int num11 = (int) soundReader.ReadUInt16(); uint num12 = soundReader.ReadUInt32(); uint num13 = soundReader.ReadUInt32(); uint num14 = soundReader.ReadUInt32(); int num15 = (int) soundReader.ReadUInt32(); soundReader.ReadUInt32(); int num16 = (int) soundReader.ReadUInt32(); uint num17 = soundReader.ReadUInt32(); soundReader.ReadUInt32(); soundReader.ReadUInt32(); soundReader.ReadUInt32(); this.name = Encoding.UTF8.GetString(soundReader.ReadBytes(64)).Replace("\0", ""); fileStream.Seek((long) num17, SeekOrigin.Begin); this.waveBanks = new WaveBank[(IntPtr) num8]; for (int index1 = 0; (long) index1 < (long) num8; ++index1) { string index2 = Encoding.UTF8.GetString(soundReader.ReadBytes(64)).Replace("\0", ""); this.waveBanks[index1] = this.audioengine.Wavebanks[index2]; } fileStream.Seek((long) num14, SeekOrigin.Begin); string[] strArray = Encoding.UTF8.GetString(soundReader.ReadBytes((int) num10)).Split(new char[1]); fileStream.Seek((long) num12, SeekOrigin.Begin); for (int index = 0; (long) index < (long) num4; ++index) { soundReader.ReadByte(); uint soundOffset = soundReader.ReadUInt32(); XactSound sound = new XactSound(this, soundReader, soundOffset); Cue cue = new Cue(this.audioengine, strArray[index], sound); this.cues.Add(cue.Name, cue); } fileStream.Seek((long) num13, SeekOrigin.Begin); for (int index1 = 0; (long) index1 < (long) num5; ++index1) { Cue cue; if (((int) soundReader.ReadByte() >> 2 & 1) != 0) { uint soundOffset = soundReader.ReadUInt32(); int num18 = (int) soundReader.ReadUInt32(); XactSound sound = new XactSound(this, soundReader, soundOffset); cue = new Cue(this.audioengine, strArray[(long) num4 + (long) index1], sound); } else { uint num18 = soundReader.ReadUInt32(); soundReader.ReadUInt32(); long position = fileStream.Position; fileStream.Seek((long) num18, SeekOrigin.Begin); uint num19 = (uint) soundReader.ReadUInt16(); uint num20 = (uint) soundReader.ReadUInt16(); int num21 = (int) soundReader.ReadByte(); int num22 = (int) soundReader.ReadUInt16(); int num23 = (int) soundReader.ReadByte(); XactSound[] _sounds = new XactSound[(IntPtr) num19]; float[] _probs = new float[(IntPtr) num19]; uint num24 = num20 >> 3 & 7U; for (int index2 = 0; (long) index2 < (long) num19; ++index2) { byte num25; byte num26; switch (num24) { case 0U: uint trackIndex1 = (uint) soundReader.ReadUInt16(); byte waveBankIndex1 = soundReader.ReadByte(); num25 = soundReader.ReadByte(); num26 = soundReader.ReadByte(); _sounds[index2] = new XactSound(this.GetWave(waveBankIndex1, trackIndex1)); break; case 1U: uint soundOffset = soundReader.ReadUInt32(); num25 = soundReader.ReadByte(); num26 = soundReader.ReadByte(); _sounds[index2] = new XactSound(this, soundReader, soundOffset); break; case 4U: uint trackIndex2 = (uint) soundReader.ReadUInt16(); byte waveBankIndex2 = soundReader.ReadByte(); _sounds[index2] = new XactSound(this.GetWave(waveBankIndex2, trackIndex2)); break; default: throw new NotImplementedException(); } } fileStream.Seek(position, SeekOrigin.Begin); cue = new Cue(strArray[(long) num4 + (long) index1], _sounds, _probs); } int num27 = (int) soundReader.ReadUInt32(); int num28 = (int) soundReader.ReadByte(); int num29 = (int) soundReader.ReadByte(); this.cues.Add(cue.Name, cue); } soundReader.Close(); fileStream.Close(); this.loaded = true; }
/// <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) { _audioengine = audioEngine; fileName = FileHelpers.NormalizeFilePathSeparators(fileName); #if !ANDROID using (var stream = TitleContainer.OpenStream(fileName)) { #else using (var fileStream = Game.Activity.Assets.Open(fileName)) { MemoryStream stream = new MemoryStream(); fileStream.CopyTo(stream); stream.Position = 0; #endif 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(); // TODO: This does not match XNA, XNA uses 43. if (formatVersion != 46) { 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); Cue cue = new Cue(_audioengine, cueNames[i], sound); _cues.Add(cue.Name, cue); } } // Complex cues if (numComplexCues > 0) { stream.Seek(complexCuesOffset, SeekOrigin.Begin); for (int i = 0; i < numComplexCues; i++) { Cue cue; 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); cue = new Cue(_audioengine, cueNames[numSimpleCues + i], sound); } 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); break; } case 3: { uint soundOffset = reader.ReadUInt32(); var weightMin = reader.ReadSingle(); var weightMax = reader.ReadSingle(); var varFlags = reader.ReadUInt32(); var linger = (varFlags & 0x01) == 0x01; var oldPosition = stream.Position; stream.Seek(soundOffset, SeekOrigin.Begin); cueSounds[j] = new XactSound(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); cue = new Cue(_audioengine, cueNames[numSimpleCues + i], cueSounds, probs); } // Instance limiting var instanceLimit = reader.ReadByte(); var fadeInSec = reader.ReadUInt16() / 1000.0f; var fadeOutSec = reader.ReadUInt16() / 1000.0f; var instanceFlags = reader.ReadByte(); _cues.Add(cue.Name, cue); } } } } }
internal Cue (AudioEngine engine, string cuename, XactSound sound) { this.engine = engine; name = cuename; sounds = new XactSound[1]; sounds[0] = sound; probs = new float[1]; probs[0] = 1.0f; }
/// <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) { _audioengine = audioEngine; fileName = FileHelpers.NormalizeFilePathSeparators(fileName); #if !ANDROID using (var stream = TitleContainer.OpenStream(fileName)) { #else using (var fileStream = Game.Activity.Assets.Open(fileName)) { MemoryStream stream = new MemoryStream(); fileStream.CopyTo(stream); stream.Position = 0; #endif 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 != 46) 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 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); Cue cue = new Cue(_audioengine, cueNames[i], sound); _cues.Add(cue.Name, cue); } // Complex cues stream.Seek(complexCuesOffset, SeekOrigin.Begin); for (int i=0; i<numComplexCues; i++) { Cue cue; 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); cue = new Cue(_audioengine, cueNames[numSimpleCues + i], sound); } 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(this, reader); stream.Seek(oldPosition, SeekOrigin.Begin); break; } case 3: { uint soundOffset = reader.ReadUInt32(); var weightMin = reader.ReadSingle(); var weightMax = reader.ReadSingle(); var varFlags = reader.ReadUInt32(); var linger = (varFlags & 0x01) == 0x01; var oldPosition = stream.Position; stream.Seek(soundOffset, SeekOrigin.Begin); cueSounds[j] = new XactSound(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); cue = new Cue(_audioengine, cueNames[numSimpleCues+i], cueSounds, probs); } // Instance limiting var instanceLimit = reader.ReadByte(); var fadeInSec = reader.ReadUInt16() / 1000.0f; var fadeOutSec = reader.ReadUInt16() / 1000.0f; var instanceFlags = reader.ReadByte(); _cues.Add(cue.Name, cue); } } } }
private void Load() { using (FileStream fileStream = new FileStream(this.filename, FileMode.Open)) { using (BinaryReader soundReader = new BinaryReader((Stream)fileStream)) { if ((int)soundReader.ReadUInt32() != 1262634067) { throw new Exception("Bad soundbank format"); } int num1 = (int)soundReader.ReadUInt16(); int num2 = (int)soundReader.ReadUInt16(); int num3 = (int)soundReader.ReadUInt16(); int num4 = (int)soundReader.ReadUInt32(); int num5 = (int)soundReader.ReadUInt32(); int num6 = (int)soundReader.ReadByte(); uint num7 = (uint)soundReader.ReadUInt16(); uint num8 = (uint)soundReader.ReadUInt16(); int num9 = (int)soundReader.ReadUInt16(); int num10 = (int)soundReader.ReadUInt16(); uint num11 = (uint)soundReader.ReadByte(); int num12 = (int)soundReader.ReadUInt16(); uint num13 = (uint)soundReader.ReadUInt16(); int num14 = (int)soundReader.ReadUInt16(); uint num15 = soundReader.ReadUInt32(); uint num16 = soundReader.ReadUInt32(); uint num17 = soundReader.ReadUInt32(); int num18 = (int)soundReader.ReadUInt32(); int num19 = (int)soundReader.ReadUInt32(); int num20 = (int)soundReader.ReadUInt32(); uint num21 = soundReader.ReadUInt32(); int num22 = (int)soundReader.ReadUInt32(); int num23 = (int)soundReader.ReadUInt32(); int num24 = (int)soundReader.ReadUInt32(); this.name = Encoding.UTF8.GetString(soundReader.ReadBytes(64)).Replace("\0", ""); fileStream.Seek((long)num21, SeekOrigin.Begin); this.waveBanks = new WaveBank[(IntPtr)num11]; for (int index1 = 0; (long)index1 < (long)num11; ++index1) { string index2 = Encoding.UTF8.GetString(soundReader.ReadBytes(64)).Replace("\0", ""); this.waveBanks[index1] = this.audioengine.Wavebanks[index2]; } fileStream.Seek((long)num17, SeekOrigin.Begin); string[] strArray = Encoding.UTF8.GetString(soundReader.ReadBytes((int)num13)).Split(new char[1]); fileStream.Seek((long)num15, SeekOrigin.Begin); for (int index = 0; (long)index < (long)num7; ++index) { int num25 = (int)soundReader.ReadByte(); uint soundOffset = soundReader.ReadUInt32(); XactSound sound = new XactSound(this, soundReader, soundOffset); Cue cue = new Cue(this.audioengine, strArray[index], sound); this.cues.Add(cue.Name, cue); } fileStream.Seek((long)num16, SeekOrigin.Begin); for (int index1 = 0; (long)index1 < (long)num8; ++index1) { Cue cue; if (((int)soundReader.ReadByte() >> 2 & 1) != 0) { uint soundOffset = soundReader.ReadUInt32(); int num25 = (int)soundReader.ReadUInt32(); XactSound sound = new XactSound(this, soundReader, soundOffset); cue = new Cue(this.audioengine, strArray[(long)num7 + (long)index1], sound); } else { uint num25 = soundReader.ReadUInt32(); int num26 = (int)soundReader.ReadUInt32(); long position = fileStream.Position; fileStream.Seek((long)num25, SeekOrigin.Begin); uint num27 = (uint)soundReader.ReadUInt16(); uint num28 = (uint)soundReader.ReadUInt16(); int num29 = (int)soundReader.ReadByte(); int num30 = (int)soundReader.ReadUInt16(); int num31 = (int)soundReader.ReadByte(); XactSound[] _sounds = new XactSound[(IntPtr)num27]; float[] _probs = new float[(IntPtr)num27]; uint num32 = num28 >> 3 & 7U; for (int index2 = 0; (long)index2 < (long)num27; ++index2) { switch (num32) { case 0U: uint trackIndex1 = (uint)soundReader.ReadUInt16(); byte waveBankIndex1 = soundReader.ReadByte(); int num33 = (int)soundReader.ReadByte(); int num34 = (int)soundReader.ReadByte(); _sounds[index2] = new XactSound(this.GetWave(waveBankIndex1, trackIndex1)); break; case 1U: uint soundOffset = soundReader.ReadUInt32(); int num35 = (int)soundReader.ReadByte(); int num36 = (int)soundReader.ReadByte(); _sounds[index2] = new XactSound(this, soundReader, soundOffset); break; case 4U: uint trackIndex2 = (uint)soundReader.ReadUInt16(); byte waveBankIndex2 = soundReader.ReadByte(); _sounds[index2] = new XactSound(this.GetWave(waveBankIndex2, trackIndex2)); break; default: throw new NotImplementedException(); } } fileStream.Seek(position, SeekOrigin.Begin); cue = new Cue(strArray[(long)num7 + (long)index1], _sounds, _probs); } int num37 = (int)soundReader.ReadUInt32(); int num38 = (int)soundReader.ReadByte(); int num39 = (int)soundReader.ReadByte(); this.cues.Add(cue.Name, cue); } } } this.loaded = true; }
/// <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 } } } }
/// <summary>Requests playback of a prepared or preparing Cue.</summary> /// <remarks>Calling Play when the Cue already is playing can result in an InvalidOperationException.</remarks> public void Play() { if (!engine._activeCues.Contains(this)) engine._activeCues.Add(this); //TODO: Probabilities var index = XactHelpers.Random.Next(sounds.Length); curSound = sounds[index]; curSound.Volume = volume; curSound.Play(); }
//Defer loading because some programs load soundbanks before wavebanks private void Load() { #if !ANDROID using (Stream soundbankstream = TitleContainer.OpenStream(filename)) { #else using (var fileStream = Game.Activity.Assets.Open(filename)) { MemoryStream soundbankstream = new MemoryStream(); fileStream.CopyTo(soundbankstream); soundbankstream.Position = 0; #endif using (BinaryReader soundbankreader = new BinaryReader(soundbankstream)) { //Parse the SoundBank. //Thanks to Liandril for "xactxtract" for some of the offsets uint magic = soundbankreader.ReadUInt32(); if (magic != 0x4B424453) //"SDBK" { throw new Exception("Bad soundbank format"); } uint toolVersion = soundbankreader.ReadUInt16(); uint formatVersion = soundbankreader.ReadUInt16(); if (formatVersion != 46) { #if DEBUG System.Diagnostics.Debug.WriteLine("Warning: SoundBank format not supported"); #endif } uint crc = soundbankreader.ReadUInt16(); //TODO: Verify crc (FCS16) uint lastModifiedLow = soundbankreader.ReadUInt32(); uint lastModifiedHigh = soundbankreader.ReadUInt32(); uint platform = soundbankreader.ReadByte(); //??? uint numSimpleCues = soundbankreader.ReadUInt16(); uint numComplexCues = soundbankreader.ReadUInt16(); soundbankreader.ReadUInt16(); //unkn uint numTotalCues = soundbankreader.ReadUInt16(); uint numWaveBanks = soundbankreader.ReadByte(); uint numSounds = soundbankreader.ReadUInt16(); uint cueNameTableLen = soundbankreader.ReadUInt16(); soundbankreader.ReadUInt16(); //unkn uint simpleCuesOffset = soundbankreader.ReadUInt32(); uint complexCuesOffset = soundbankreader.ReadUInt32(); //unkn uint cueNamesOffset = soundbankreader.ReadUInt32(); soundbankreader.ReadUInt32(); //unkn uint variationTablesOffset = soundbankreader.ReadUInt32(); soundbankreader.ReadUInt32(); //unkn uint waveBankNameTableOffset = soundbankreader.ReadUInt32(); uint cueNameHashTableOffset = soundbankreader.ReadUInt32(); uint cueNameHashValsOffset = soundbankreader.ReadUInt32(); uint soundsOffset = soundbankreader.ReadUInt32(); name = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64), 0, 64).Replace("\0", ""); //parse wave bank name table soundbankstream.Seek(waveBankNameTableOffset, SeekOrigin.Begin); waveBanks = new WaveBank[numWaveBanks]; for (int i = 0; i < numWaveBanks; i++) { string bankname = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64), 0, 64).Replace("\0", ""); waveBanks[i] = audioengine.Wavebanks[bankname]; } //parse cue name table soundbankstream.Seek(cueNamesOffset, SeekOrigin.Begin); string[] cueNames = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes((int)cueNameTableLen), 0, (int)cueNameTableLen).Split('\0'); soundbankstream.Seek(simpleCuesOffset, SeekOrigin.Begin); for (int i = 0; i < numSimpleCues; i++) { byte flags = soundbankreader.ReadByte(); uint soundOffset = soundbankreader.ReadUInt32(); XactSound sound = new XactSound(this, soundbankreader, soundOffset); Cue cue = new Cue(audioengine, cueNames[i], sound); cues.Add(cue.Name, cue); } soundbankstream.Seek(complexCuesOffset, SeekOrigin.Begin); for (int i = 0; i < numComplexCues; i++) { Cue cue; byte flags = soundbankreader.ReadByte(); if (((flags >> 2) & 1) != 0) { //not sure :/ uint soundOffset = soundbankreader.ReadUInt32(); soundbankreader.ReadUInt32(); //unkn XactSound sound = new XactSound(this, soundbankreader, soundOffset); cue = new Cue(audioengine, cueNames[numSimpleCues + i], sound); } else { uint variationTableOffset = soundbankreader.ReadUInt32(); uint transitionTableOffset = soundbankreader.ReadUInt32(); //parse variation table long savepos = soundbankstream.Position; soundbankstream.Seek(variationTableOffset, SeekOrigin.Begin); uint numEntries = soundbankreader.ReadUInt16(); uint variationflags = soundbankreader.ReadUInt16(); soundbankreader.ReadByte(); soundbankreader.ReadUInt16(); soundbankreader.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 { uint trackIndex = soundbankreader.ReadUInt16(); byte waveBankIndex = soundbankreader.ReadByte(); byte weightMin = soundbankreader.ReadByte(); byte weightMax = soundbankreader.ReadByte(); cueSounds[j] = new XactSound(this.GetWave(waveBankIndex, trackIndex)); break; } case 1: { uint soundOffset = soundbankreader.ReadUInt32(); byte weightMin = soundbankreader.ReadByte(); byte weightMax = soundbankreader.ReadByte(); cueSounds[j] = new XactSound(this, soundbankreader, soundOffset); break; } case 4: //CompactWave { uint trackIndex = soundbankreader.ReadUInt16(); byte waveBankIndex = soundbankreader.ReadByte(); cueSounds[j] = new XactSound(this.GetWave(waveBankIndex, trackIndex)); break; } default: throw new NotSupportedException(); } } soundbankstream.Seek(savepos, SeekOrigin.Begin); cue = new Cue(cueNames[numSimpleCues + i], cueSounds, probs); } //Instance Limit soundbankreader.ReadUInt32(); soundbankreader.ReadByte(); soundbankreader.ReadByte(); cues.Add(cue.Name, cue); } } } loaded = true; }
public void Play() { //TODO: Probabilities curSound = sounds[variationRand.Next (sounds.Length)]; curSound.Volume = volume; curSound.Play (); paused = false; }