private AudioManager(Microsoft.Xna.Framework.Game game, string settingsFile, string waveBankFile, string soundBankFile) : base(game) { this.SoundEffectInstances = new List<SoundEffectInstance>(); try { this.audioEngine = new AudioEngine(settingsFile); this.waveBank = new WaveBank(this.audioEngine, waveBankFile, 0, 16); this.soundBank = new SoundBank(this.audioEngine, soundBankFile); } catch (NoAudioHardwareException) { this.audioEngine = null; this.waveBank = null; this.soundBank = null; } catch (InvalidOperationException) { this.audioEngine = null; this.waveBank = null; this.soundBank = null; } while (!this.waveBank.IsPrepared) { this.audioEngine.Update(); } }
public GameplayScreen(GraphicsDevice g, byte _gameType) { audioEngine = new AudioEngine(@"Content\Audio\Sounds.xgs"); waveBank = new WaveBank(audioEngine, @"Content\Audio\Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, @"Content\Audio\Sound Bank.xsb"); BGM = new Cue[9]; graphicsDevice = g; graphicsDevice.RenderState.DepthBufferEnable = true; spriteBatch = new SpriteBatch(g); GameOverScreen = new MessageBoxScreen(" " + Score, false); CongratulationsScreen = new MessageBoxScreen(" ", false); PauseMenu = new PauseMenuScreen(); WorldMatrix = Matrix.Identity; SwitchCue = false; PauseCue = false; GameOverState = false; tmrVibrate = new TimeSpan(); tmrVibrate = TimeSpan.Zero; sourceRect = new Rectangle(0, 0, 64, 16); GameType = _gameType; currentcue = 0; if (GameType > 0) { timespan = 10; Randomizer = new Random(); tmrTimer = new TimeSpan(); tmrTimer = TimeSpan.Zero; } }
public override void Load() { try { m_AudioEngine = new AudioEngine(m_RootDirectory + "sounds.xgs"); if (m_AudioEngine != null) { m_WaveBank = new WaveBank(m_AudioEngine, (m_RootDirectory + "Wave Bank.xwb")); m_SoundBank = new SoundBank(m_AudioEngine, (m_RootDirectory + "Sound Bank.xsb")); // Get sound categories AudioCategory soundCategory = m_AudioEngine.GetCategory("Sounds"); AudioCategory musicCategory = m_AudioEngine.GetCategory("Music"); // Set into the custom categories m_SoundCategory = new CustomAudioCategory(soundCategory); m_MusicCategory = new CustomAudioCategory(musicCategory); } } catch (Exception e) { Console.WriteLine(e.ToString()); } }
public GameRoot() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; Instance = this; //http://msdn.microsoft.com/en-us/library/dd231915%28v=xnagamestudio.31%29.aspx nores on how to load audio engine. had to add xact.dll reference located in programfiles/microsoftxna/.../win/xact.dll //http://xboxforums.create.msdn.com/forums/p/102228/608489.aspx how to find other audio devices. // Initialize audio objects. engine = new AudioEngine(@"Content\Audio\Xact.xgs",TimeSpan.Zero,"{0.0.0.00000000}.{a26fe1c0-9b55-4670-a6fd-76d91685f704}"); soundBank = new SoundBank(engine, @"Content\Audio\Sound Bank.xsb"); waveBank = new WaveBank(engine, @"Content\Audio\Wave Bank.xwb"); //Console.WriteLine("SOUND ENGINE: " + engine.RendererDetails.ToString()); used to determine the redndererID //foreach (var r in engine.RendererDetails) //{ // Console.WriteLine(r.FriendlyName +","+ r.RendererId); //} graphics.PreferredBackBufferWidth = 1680;//(int)DisplaySize.X-150; graphics.PreferredBackBufferHeight = 1050;//(int)DisplaySize.Y -350; bloom = new BloomComponent(this); Components.Add(bloom); bloom.Settings = new BloomSettings(null, .25f, 4, 2, 1, 1.5f, 1); IsFixedTimeStep = true; //TargetElapsedTime = TimeSpan.FromSeconds(1.0 / 120); }
public cAudio() { _instance = this; _engine = new AudioEngine("Resources/Audio/Portal2DSounds.xgs"); _waveBank = new WaveBank(_engine, "Resources/Audio/Wave Bank.xwb"); _soundBank = new SoundBank(_engine, "Resources/Audio/Sound Bank.xsb"); }
public MoteurAudio() { engine = new AudioEngine(@"Content\Sons\Ambiance sonore.xgs"); waveBank = new WaveBank(engine, @"Content\Sons\Wave Bank.xwb"); soundBank = new SoundBank(engine, @"Content\Sons\Sound Bank.xsb"); musiques = new Song[2]; }
private AudioEngineManager() { //create and use appropriate XACT objects audioEngine = new AudioEngine("Content\\Audio\\datx02.xgs"); soundBank = new SoundBank(audioEngine, "Content\\Audio\\SoundEffects.xsb"); waveBank = new WaveBank(audioEngine, "Content\\Audio\\SoundEffectWaves.xwb"); }
public FieldPong() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); graphics.PreferredBackBufferWidth = 1024; graphics.PreferredBackBufferHeight = 768; graphics.MinimumPixelShaderProfile = ShaderProfile.PS_2_0; graphics.SynchronizeWithVerticalRetrace = true; physicsSimulator = new PhysicsSimulator(new Vector2(0)); physicsSimulator.AllowedPenetration = 0.3f; physicsSimulator.BiasFactor = 1.0f; Services.AddService(typeof(PhysicsSimulator), physicsSimulator); screenManager = new ScreenManager(this); Components.Add(screenManager); bloomProcessor = new BloomPostProcessor(this); Components.Add(bloomProcessor); // Uncomment this to monitor the FPS: //fpsCounter = new FrameRateCounter(this); //Components.Add(fpsCounter); audioEngine = new AudioEngine("Content\\Audio\\FieldPongAudio.xgs"); waveBank = new WaveBank(audioEngine, "Content\\Audio\\Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, "Content\\Audio\\Sound Bank.xsb"); backgroundMusic = soundBank.GetCue("GameSong0010 16 Bit"); backgroundMusic.Play(); }
/// <summary> /// Create sound /// </summary> static Sound() { try { string dir = Directories.SoundsDirectory; audioEngine = new AudioEngine( Path.Combine(dir, "XnaShooter.xgs")); waveBank = new WaveBank(audioEngine, Path.Combine(dir, "Wave Bank.xwb")); // Dummy wavebank call to get rid of the warning that waveBank is // never used (well it is used, but only inside of XNA). if (waveBank != null) soundBank = new SoundBank(audioEngine, Path.Combine(dir, "Sound Bank.xsb")); // Get the music category to change the music volume and stop music musicCategory = audioEngine.GetCategory("Music"); } // try catch (Exception ex) { // Audio creation crashes in early xna versions, log it and ignore it! Log.Write("Failed to create sound class: " + ex.ToString()); } // catch }
public SoundBank(AudioEngine audioEngine, string filename) { audioengine = audioEngine; // Check for windows-style directory separator character filename = filename.Replace('\\',Path.DirectorySeparatorChar); BinaryReader soundbankreader = new BinaryReader(new FileStream(filename, FileMode.Open)); //byte[] identifier = soundbankreader.ReadBytes(4); soundbankreader.BaseStream.Seek(30, SeekOrigin.Begin); int cuelength = soundbankreader.ReadInt32(); soundbankreader.BaseStream.Seek(42, SeekOrigin.Begin); int cueoffset = soundbankreader.ReadInt32(); soundbankreader.BaseStream.Seek(74, SeekOrigin.Begin); name = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0",""); targetname = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0", ""); soundbankreader.BaseStream.Seek(cueoffset, SeekOrigin.Begin); cues = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(cuelength)).Split('\0'); }
public static void Initialize() { audioEngine = new AudioEngine("Content/Sounds.xgs"); soundBank = new SoundBank(audioEngine, "Content/Sound Bank.xsb"); waveBank = new WaveBank(audioEngine, "Content/Wave Bank.xwb"); soundsPlaying = new List<Cue>(); }
public NunChuckEnemy(Random rand, AudioEngine engine, SoundBank soundBank, WaveBank waveBank) { this.engine = engine; this.soundBank = soundBank; this.waveBank = waveBank; int side = rand.Next(5); if (side == 1) { position = new Vector2(rand.Next(GraphicsViewport.Width), 0f); } if (side == 2) { position = new Vector2(0f, rand.Next(GraphicsViewport.Height)); } if (side == 3) { position = new Vector2(rand.Next(GraphicsViewport.Width), GraphicsViewport.Height); } if (side == 4) { position = new Vector2(GraphicsViewport.Width, rand.Next(GraphicsViewport.Height)); } origin = new Vector2(0f, 0f); rotation = 0; velocity = 10; boxSize = 25; tint = new Color(255, 255, 255, 255); collided = false; fired = false; }
private SoundEngine() { return; _engine = new AudioEngine("Content\\Sounds\\Sounds.xgs"); _wavebank = new WaveBank(_engine, "Content\\Sounds\\Wave Bank.xwb"); _soundbank = new SoundBank(_engine, "Content\\Sounds\\Sound Bank.xsb"); }
public AudioManager(AudioEngine e, WaveBank wb, SoundBank sb) { Engine = e; WaveBank = wb; SoundBank = sb; singleton = this; }
/// <summary> /// Create an empty world. /// </summary> /// <param name="parentScreen">The screen this world will be updated in.</param> public World(Screen parentScreen, Player player) : base(parentScreen) { this.worldObjects = new List<WorldObject>(); this.player = player; ParentScreen.Components.Add(player); this.interactiveLayers = new Dictionary<int, TileMapLayer>(); this.parallaxLayers = new Dictionary<int, TileMapLayer>(); batchService = (ISpriteBatchService)this.Game.Services.GetService(typeof(ISpriteBatchService)); otherMaps = new List<TileMap>(); //Set up Sound systems audioEngine = new AudioEngine("Content\\System\\Sounds\\Win\\SoundFX.xgs"); soundBank = new SoundBank(audioEngine, "Content\\System\\Sounds\\Win\\GameSoundBank.xsb"); waveBank = new WaveBank(audioEngine, "Content\\System\\Sounds\\Win\\GameWavs.xwb"); // Set up our collision systems: spriteCollisionManager = new SpriteSpriteCollisionManager(this.Game, batchService, 40, 40); ParentScreen.Components.Add(spriteCollisionManager); bgm = this.Game.Content.Load<Song>("System\\Music\\DesertBGM"); MediaPlayer.IsRepeating = true; MediaPlayer.Play(bgm); LoadCtorInfos(); }
public WaveBank( AudioEngine audioEngine, string streamingWaveBankFilename, int offset, short packetsize ) { /* Note that offset and packetsize go unused, * because we're frauds and aren't actually streaming. * -flibit */ if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(streamingWaveBankFilename)) { throw new ArgumentNullException("streamingWaveBankFilename"); } INTERNAL_waveBankReader = new BinaryReader( TitleContainer.OpenStream(streamingWaveBankFilename) ); LoadWaveBank(audioEngine, INTERNAL_waveBankReader, true); }
public static void InitializeAudioManager(ContentManager cm) { audioEngine = new AudioEngine("Content//Music//music.xgs"); waveBank = new WaveBank(audioEngine, "Content//Music//Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, "Content//Music//Sound Bank.xsb"); //TODO: initialize SoundEffects worldShatter = cm.Load<SoundEffect>("SFX/DimensionShatter"); doorClose = cm.Load<SoundEffect>("SFX/DoorClose"); doorOpen = cm.Load<SoundEffect>("SFX/DoorOpen"); portal = cm.Load<SoundEffect>("SFX/EnterPortal"); bridgeBarrier = cm.Load<SoundEffect>("SFX/HitBarrier"); objectDestroyed = cm.Load<SoundEffect>("SFX/ObjectDestroyed"); playerDie = cm.Load<SoundEffect>("SFX/PlayerDie"); playerRevive = cm.Load<SoundEffect>("SFX/PlayerRevive"); portalItem = cm.Load<SoundEffect>("SFX/PortalItemGet"); switchActivate = cm.Load<SoundEffect>("SFX/SwitchActivate"); switchDeactivate = cm.Load<SoundEffect>("SFX/SwitchDeactivate"); bridgeBreaking = cm.Load<SoundEffect>("SFX/ObjectDestroyed"); //Change playerJump = cm.Load<SoundEffect>("SFX/PlayerJump"); playerLand = cm.Load<SoundEffect>("SFX/PlayerLand"); playerPsyActivate = cm.Load<SoundEffect>("SFX/PsyActivate"); playerPsyDeactivate = cm.Load<SoundEffect>("SFX/PsyDeactivate"); checkpoint = worldShatter; //Change? signal = bridgeBarrier; //Do -> Change? pause = cm.Load<SoundEffect>("SFX/pause"); //Change //menuMove = cm.Load<SoundEffect>("SFX/menuBlip"); menuMove = bridgeBarrier; //menuSelect = cm.Load<SoundEffect>("SFX/menuSelect"); menuSelect = worldShatter; }
public override void Initialize() { engine = new AudioEngine("Content\\audio\\siegeAudio.xgs"); waveBank = new WaveBank(engine, "Content\\audio\\Wave Bank.xwb"); soundBank = new SoundBank(engine, "Content\\audio\\Sound Bank.xsb"); base.Initialize(); }
public AudioManager(Game game, string settingsFile, string soundbankFile, string soundEffectsWaveBankFile, string musicWaveBankFile) : base(game) { _audioEngine = new AudioEngine(settingsFile); _soundBank = new SoundBank(_audioEngine, soundbankFile); _soundEffectsBank = new WaveBank(_audioEngine, soundEffectsWaveBankFile); _musicBank = new WaveBank(_audioEngine, musicWaveBankFile, 0, 16); }
public Audio(Game game) : base(game) { // Load all the audio data audioEngine = new AudioEngine(@"Content\Audio\FinalProject.xgs"); waveBank = new WaveBank(audioEngine, @"Content\Audio\Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, @"Content\Audio\Sound Bank.xsb"); }
protected override void LoadGraphicsContent(bool loadAllContent) { audio = new AudioEngine("Content/Audio/TOBam.xgs"); waveBank = new WaveBank(audio, "Content/Audio/Wave Bank.xwb"); soundBank = new SoundBank(audio, "Content/Audio/Sound Bank.xsb"); TOBamGame.soundBank.PlayCue("required_ttc"); base.LoadGraphicsContent(loadAllContent); }
public SoundManager() { audioEngine = new AudioEngine(@"Content/Sounds/GameSounds.xgs"); waveBank = new WaveBank(audioEngine, @"Content/Sounds/Wave Bank.xwb"); soundBank = new SoundBank(audioEngine, @"Content/Sounds/Sound Bank.xsb"); Songs = new Dictionary<string, SoundEffectInstance>(); }
public DefenderMusic( SoundBank sounds, AudioEngine engine ) { mSounds = sounds; mEngine = engine; mMusic = sounds.GetCue( "stage_music" ); mMusicName = mMusic.Name; mVolume = 1.0f; mMusic.Play(); }
public Audio(string clip, string settings, string waveBank, string soundBank, Game game) : base(game) { this.audioEngine = new AudioEngine(this.Game.Content.RootDirectory + @"\" + settings); this.waveBank = new WaveBank(this.audioEngine, this.Game.Content.RootDirectory + @"\" + waveBank); this.soundBank = new SoundBank(this.audioEngine, this.Game.Content.RootDirectory + @"\" + soundBank); this.sound = this.soundBank.GetCue(clip); }
public Audio(string ae, string wb, string sb, string cn) { this.audioEngine = new AudioEngine(ae); this.waveBank = new WaveBank(audioEngine, wb); this.soundBank = new SoundBank(audioEngine, sb); this.cueName = cn; playStat = false; }
/// <summary> /// Constructs the manager for audio playback of all cues. /// </summary> /// <param name="game">The game that this component will be attached to.</param> /// <param name="settingsFile">The filename of the XACT settings file.</param> /// <param name="waveBankFile">The filename of the XACT wavebank file.</param> /// <param name="soundBankFile">The filename of the XACT soundbank file.</param> public AudioManager(Game game, string settingsFile, string waveBankFile, string soundBankFile) : base(game) { engine = new AudioEngine(settingsFile); waves = new WaveBank(engine, waveBankFile); sounds = new SoundBank(engine, soundBankFile); }
public AudioEM(Microsoft.Xna.Framework.Game game) { content = new ContentManager(game.Services, "main"); audioEngine = new AudioEngine(@"main\audio\soundEngine.xgs"); musicWaves = new WaveBank(audioEngine, @"main\audio\musicWaves.xwb"); musicSounds = new SoundBank(audioEngine, @"main\audio\musicSounds.xsb"); }
public Game() { new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; _engine = new AudioEngine("Content\\Sounds.xgs"); _soundBank = new SoundBank(_engine, "Content\\Sound Bank.xsb"); _waveBank = new WaveBank(_engine, "Content\\Wave Bank.xwb"); }
public void LoadContent(string path) { engine = new AudioEngine(path + "sounds.xgs"); sounds = new SoundBank(engine, path + "Sound Bank.xsb"); waves = new WaveBank(engine, path + "Wave Bank.xwb"); categories = new Dictionary<string, AudioCategory>(); categories.Add("Music", engine.GetCategory("Music")); categories.Add("Default", engine.GetCategory("Default")); }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { isGameRun = true; random = new Random(); //Загружаем аудиоресурсы для игры audioEngine = new AudioEngine("Content\\Audio\\SpaceInvaders.xgs"); waveBank = new WaveBank(audioEngine, "Content\\Audio\\Sounds.xwb"); soundBank = new SoundBank(audioEngine, "Content\\Audio\\SoundBank.xsb"); //Присваиваем переменной ссылку на закладку с именем Music curSong = random.Next(1, numberOfSongs + 1); musicCue = soundBank.GetCue(curSong.ToString()); //Включаем проигрывание фоновой музыки musicCue.Play(); base.Initialize(); }
public WaveBank( AudioEngine audioEngine, string streamingWaveBankFilename, int offset, short packetsize ) { if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(streamingWaveBankFilename)) { throw new ArgumentNullException("streamingWaveBankFilename"); } string safeName = MonoGame.Utilities.FileHelpers.NormalizeFilePathSeparators( streamingWaveBankFilename ); if (!Path.IsPathRooted(safeName)) { safeName = Path.Combine( TitleLocation.Path, safeName ); } ioStream = FAudio.FAudio_fopen(safeName); FAudio.FACTStreamingParameters settings = new FAudio.FACTStreamingParameters(); settings.file = ioStream; FAudio.FACTAudioEngine_CreateStreamingWaveBank( audioEngine.handle, ref settings, out handle ); engine = audioEngine; selfReference = new WeakReference(this, true); engine.RegisterWaveBank(handle, selfReference); IsDisposed = false; }
public WaveBank( AudioEngine audioEngine, string nonStreamingWaveBankFilename ) { if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(nonStreamingWaveBankFilename)) { throw new ArgumentNullException("nonStreamingWaveBankFilename"); } using (Stream stream = TitleContainer.OpenStream(nonStreamingWaveBankFilename)) using (BinaryReader reader = new BinaryReader(stream)) { LoadWaveBank(audioEngine, reader, false); } }
protected virtual void Dispose(bool disposing) { // If you need thread safety, use a lock around these // operations, as well as in your methods that use the resource. if (!_disposed) { if (disposing) { Cleanup(); } // Indicate that the instance has been disposed. _disposed = true; if(currentInstance == this) { currentInstance = null; } // managed resource cleanup here. } }
internal AudioCategory(AudioEngine audioengine, string name, BinaryReader reader) { this.name = name; engine = audioengine; maxInstances = reader.ReadByte(); instanceLimit = maxInstances != 0xff; fadeIn = (reader.ReadUInt16() / 1000f); fadeOut = (reader.ReadUInt16() / 1000f); byte instanceFlags = reader.ReadByte(); fadeType = (CrossfadeType)(instanceFlags & 0x7); instanceBehaviour = (MaxInstanceBehaviour)(instanceFlags >> 3); reader.ReadUInt16(); //unkn byte vol = reader.ReadByte(); //volume in unknown format //lazy 4-param fitting: //0xff 6.0 //0xca 2.0 //0xbf 1.0 //0xb4 0.0 //0x8f -4.0 //0x5a -12.0 //0x14 -38.0 //0x00 -96.0 var a = -96.0; var b = 0.432254984608615; var c = 80.1748600297963; var d = 67.7385212334047; volume = (float)(((a - d) / (1 + (Math.Pow(vol / c, b)))) + d); byte visibilityFlags = reader.ReadByte(); isBackgroundMusic = (visibilityFlags & 0x1) != 0; isPublic = (visibilityFlags & 0x2) != 0; }
internal Cue( AudioEngine audioEngine, List <string> waveBankNames, string name, CueData data, bool managed ) { INTERNAL_baseEngine = audioEngine; Name = name; INTERNAL_data = data; foreach (XACTSound curSound in data.Sounds) { if (!curSound.HasLoadedTracks) { curSound.LoadTracks( INTERNAL_baseEngine, waveBankNames ); } } INTERNAL_isManaged = managed; INTERNAL_category = INTERNAL_baseEngine.INTERNAL_initCue( this, data.Category ); INTERNAL_userControlledPlaying = false; INTERNAL_isPositional = false; INTERNAL_queuedPlayback = false; INTERNAL_queuedPaused = false; INTERNAL_instancePool = new List <SoundEffectInstance>(); INTERNAL_instanceVolumes = new List <float>(); INTERNAL_instancePitches = new List <float>(); }
public SoundBank(AudioEngine audioEngine, string filename) { if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } byte[] buffer = TitleContainer.ReadAllBytes(filename); GCHandle pin = GCHandle.Alloc(buffer, GCHandleType.Pinned); FAudio.FACTAudioEngine_CreateSoundBank( audioEngine.handle, pin.AddrOfPinnedObject(), (uint)buffer.Length, 0, 0, out handle ); pin.Free(); buffer = null; engine = audioEngine; selfReference = new WeakReference(this, true); dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS(); dspSettings.SrcChannelCount = 1; dspSettings.DstChannelCount = engine.channels; dspSettings.pMatrixCoefficients = Marshal.AllocHGlobal( 4 * (int)dspSettings.SrcChannelCount * (int)dspSettings.DstChannelCount ); engine.RegisterSoundBank(handle, selfReference); IsDisposed = false; }
public SoundBank(AudioEngine audioEngine, string filename) { audioengine = audioEngine; BinaryReader soundbankreader = new BinaryReader(new FileStream(filename, FileMode.Open)); //byte[] identifier = soundbankreader.ReadBytes(4); soundbankreader.BaseStream.Seek(30, SeekOrigin.Begin); int cuelength = soundbankreader.ReadInt32(); soundbankreader.BaseStream.Seek(42, SeekOrigin.Begin); int cueoffset = soundbankreader.ReadInt32(); soundbankreader.BaseStream.Seek(74, SeekOrigin.Begin); name = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0", ""); targetname = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(64)).Replace("\0", ""); soundbankreader.BaseStream.Seek(cueoffset, SeekOrigin.Begin); cues = System.Text.Encoding.UTF8.GetString(soundbankreader.ReadBytes(cuelength)).Split('\0'); }
public SoundBank(AudioEngine audioEngine, string filename) { if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } IntPtr bufferLen; IntPtr buffer = TitleContainer.ReadToPointer(filename, out bufferLen); FAudio.FACTAudioEngine_CreateSoundBank( audioEngine.handle, buffer, (uint)bufferLen, 0, 0, out handle ); FNAPlatform.FreeFilePointer(buffer); engine = audioEngine; selfReference = new WeakReference(this, true); dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS(); dspSettings.SrcChannelCount = 1; dspSettings.DstChannelCount = engine.channels; dspSettings.pMatrixCoefficients = Marshal.AllocHGlobal( 4 * (int)dspSettings.SrcChannelCount * (int)dspSettings.DstChannelCount ); engine.RegisterPointer(handle, selfReference); IsDisposed = false; }
// instances only dispose of streaming audio public void Dispose() { #if !NO_FMOD if (Playing && mChannel != null) { mChannel.stop(); } if (mSound != null) { AudioEngine audioengine = GSGE.AudioManager.GetAudioManager().GetAudioEngine(); audioengine.FmodSounds.Remove(this); } if (mOwnSound && mSound != null) { FMOD.RESULT result = mSound.release(); ERRCHECK(result); } mOwnSound = false; mSound = null; mChannel = null; if (mStreamRequested != mStreamStarted) { mAbortStream = true; } else { mStreamBytes = null; mStreamRequested = false; mStreamStarted = false; } #endif }
public SoundBank(AudioEngine audioEngine, string fileName) { // Check for windows-style directory separator character filename = fileName.Replace('\\', Path.DirectorySeparatorChar); audioengine = audioEngine; }
public SoundBank(AudioEngine audioEngine, string filename) { if (audioEngine == null) { throw new ArgumentNullException("audioEngine"); } if (String.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } INTERNAL_baseEngine = audioEngine; using (Stream soundBankStream = TitleContainer.OpenStream(filename)) using (BinaryReader reader = new BinaryReader(soundBankStream)) { // Check the file header. Should be 'SDBK' if (reader.ReadUInt32() != 0x4B424453) { throw new ArgumentException("SDBK format not recognized!"); } // Check the content version. Assuming XNA4 Refresh. if (reader.ReadUInt16() != AudioEngine.ContentVersion) { throw new ArgumentException("SDBK Content version!"); } // Check the tool version. Assuming XNA4 Refresh. if (reader.ReadUInt16() != 43) { throw new ArgumentException("SDBK Tool version!"); } // CRC, unused reader.ReadUInt16(); // Last modified, unused reader.ReadUInt64(); // Unknown value, Internet suggests platform reader.ReadByte(); // Cue Counts ushort numCueSimple = reader.ReadUInt16(); ushort numCueComplex = reader.ReadUInt16(); // Unknown value reader.ReadUInt16(); // Total Cues, unused reader.ReadUInt16(); // Number of associated WaveBanks byte numWaveBanks = reader.ReadByte(); // Unknown, Internet suggest number of "sounds" reader.ReadUInt16(); // Cue Name Table Length ushort cueNameTableLength = reader.ReadUInt16(); // Unknown value reader.ReadUInt16(); // Cue Offsets uint cueSimpleOffset = reader.ReadUInt32(); uint cueComplexOffset = reader.ReadUInt32(); // Cue Name Table Offset uint cueNameTableOffset = reader.ReadUInt32(); // Unknown value reader.ReadUInt32(); // Variable Tables Offset, unused reader.ReadUInt32(); // Unknown value reader.ReadUInt32(); // WaveBank Name Table Offset uint waveBankNameTableOffset = reader.ReadUInt32(); // Cue Name Hash Offsets, unused reader.ReadUInt32(); reader.ReadUInt32(); // Unknown value, Internet suggest "sounds" offset reader.ReadUInt32(); // SoundBank Name, unused System.Text.Encoding.UTF8.GetString( reader.ReadBytes(64), 0, 64 ).Replace("\0", ""); // Parse WaveBank names soundBankStream.Seek(waveBankNameTableOffset, SeekOrigin.Begin); INTERNAL_waveBankNames = new List <string>(); for (byte i = 0; i < numWaveBanks; i += 1) { INTERNAL_waveBankNames.Add( System.Text.Encoding.UTF8.GetString( reader.ReadBytes(64), 0, 64 ).Replace("\0", "") ); } // Parse Cue name list soundBankStream.Seek(cueNameTableOffset, SeekOrigin.Begin); string[] cueNames = System.Text.Encoding.UTF8.GetString( reader.ReadBytes(cueNameTableLength), 0, cueNameTableLength ).Split('\0'); // Create our CueData Dictionary INTERNAL_cueData = new Dictionary <string, CueData>(); // Parse Simple Cues soundBankStream.Seek(cueSimpleOffset, SeekOrigin.Begin); for (ushort i = 0; i < numCueSimple; i += 1) { // Cue flags, unused reader.ReadByte(); // Cue Sound Offset uint offset = reader.ReadUInt32(); // Store this for when we're done reading the sound. long curPos = reader.BaseStream.Position; // Go to the sound in the Bank. reader.BaseStream.Seek(offset, SeekOrigin.Begin); // Parse the Sound INTERNAL_cueData.Add( cueNames[i], new CueData(new XACTSound(reader)) ); // Back to where we were... reader.BaseStream.Seek(curPos, SeekOrigin.Begin); } // Parse Complex Cues soundBankStream.Seek(cueComplexOffset, SeekOrigin.Begin); for (ushort i = 0; i < numCueComplex; i += 1) { // Cue flags byte cueFlags = reader.ReadByte(); if ((cueFlags & 0x04) != 0) // FIXME: ??? { // Cue Sound Offset uint offset = reader.ReadUInt32(); // Unknown value reader.ReadUInt32(); // Store this for when we're done reading the sound. long curPos = reader.BaseStream.Position; // Go to the sound in the bank reader.BaseStream.Seek(offset, SeekOrigin.Begin); // Parse the Sound INTERNAL_cueData.Add( cueNames[numCueSimple + i], new CueData(new XACTSound(reader)) ); // Back to where we were... reader.BaseStream.Seek(curPos, SeekOrigin.Begin); } else { // Variation Table Offset for this Cue uint offset = reader.ReadUInt32(); // Transition Table Offset for this Cue, unused reader.ReadUInt32(); // Store this for when we're done reading the Variation Table long curPos = reader.BaseStream.Position; // Seek to the Variation Table in the file reader.BaseStream.Seek(offset, SeekOrigin.Begin); // Number of Variations in the Table ushort numVariations = reader.ReadUInt16(); // Variation Table Flags ushort varTableFlags = reader.ReadUInt16(); // Unknown value reader.ReadUInt16(); // Probability Control Variable, if applicable ushort variable = reader.ReadUInt16(); // Create data for the CueData XACTSound[] cueSounds = new XACTSound[numVariations]; float[,] cueProbs = new float[numVariations, 2]; // Used to determine Variation storage format int varTableType = (varTableFlags >> 3) & 0x0007; for (ushort j = 0; j < numVariations; j += 1) { if (varTableType == 0) { // Wave with byte min/max ushort track = reader.ReadUInt16(); byte waveBank = reader.ReadByte(); byte wMin = reader.ReadByte(); byte wMax = reader.ReadByte(); // Create the Sound cueSounds[j] = new XACTSound(track, waveBank); // Calculate probability based on weight cueProbs[j, 0] = wMax / 255.0f; cueProbs[j, 1] = wMin / 255.0f; } else if (varTableType == 1) { // Complex with byte min/max uint varOffset = reader.ReadUInt32(); byte wMin = reader.ReadByte(); byte wMax = reader.ReadByte(); // Store for sound read long varPos = reader.BaseStream.Position; // Seek to the sound in the Bank reader.BaseStream.Seek(varOffset, SeekOrigin.Begin); // Read the sound cueSounds[j] = new XACTSound(reader); // Back to where we were... reader.BaseStream.Seek(varPos, SeekOrigin.Begin); // Calculate probability based on weight cueProbs[j, 0] = wMax / 255.0f; cueProbs[j, 1] = wMin / 255.0f; } else if (varTableType == 3) { // Complex with float min/max uint varOffset = reader.ReadUInt32(); float wMin = reader.ReadSingle(); float wMax = reader.ReadSingle(); // Unknown value reader.ReadUInt32(); // Store for sound read long varPos = reader.BaseStream.Position; // Seek to the sound in the Bank reader.BaseStream.Seek(varOffset, SeekOrigin.Begin); // Read the sound cueSounds[j] = new XACTSound(reader); // Back to where we were... reader.BaseStream.Seek(varPos, SeekOrigin.Begin); // Calculate probability based on weight cueProbs[j, 0] = wMax; cueProbs[j, 1] = wMin; } else if (varTableType == 4) { // Compact Wave ushort track = reader.ReadUInt16(); byte waveBank = reader.ReadByte(); // Create the Sound cueSounds[j] = new XACTSound(track, waveBank); // FIXME: Assume Sound weight is 100% cueProbs[j, 0] = 1.0f; cueProbs[j, 1] = 0.0f; } else { throw new NotSupportedException(); } } // Back to where we were... reader.BaseStream.Seek(curPos, SeekOrigin.Begin); // Add Built CueData to Dictionary INTERNAL_cueData.Add( cueNames[numCueSimple + i], new CueData( cueSounds, cueProbs, (varTableType == 3) ? INTERNAL_baseEngine.INTERNAL_getVariableName(variable) : String.Empty ) ); } // Cue instance limit byte instanceLimit = reader.ReadByte(); // Fade In/Out, unused reader.ReadUInt16(); reader.ReadUInt16(); // Cue max instance behavior byte behavior = reader.ReadByte(); INTERNAL_cueData[cueNames[numCueSimple + i]].SetLimit( instanceLimit, behavior ); } } IsDisposed = false; }
public AudioEngine(string settingsFile, TimeSpan lookAheadTime, string rendererId) { using (FileStream fileStream = File.OpenRead(settingsFile)) { using (BinaryReader reader = new BinaryReader((Stream)fileStream)) { if ((int)reader.ReadUInt32() != 1179862872) { throw new ArgumentException("XGS format not recognized"); } uint num1 = (uint)reader.ReadUInt16(); uint num2 = (uint)reader.ReadUInt16(); uint num3 = (uint)reader.ReadUInt16(); reader.ReadUInt32(); reader.ReadUInt32(); int num4 = (int)reader.ReadByte(); uint count1 = (uint)reader.ReadUInt16(); uint count2 = (uint)reader.ReadUInt16(); int num5 = (int)reader.ReadUInt16(); int num6 = (int)reader.ReadUInt16(); uint num7 = (uint)reader.ReadUInt16(); uint num8 = (uint)reader.ReadUInt16(); uint num9 = (uint)reader.ReadUInt16(); uint num10 = reader.ReadUInt32(); uint num11 = reader.ReadUInt32(); int num12 = (int)reader.ReadUInt32(); reader.ReadUInt32(); int num13 = (int)reader.ReadUInt32(); reader.ReadUInt32(); uint num14 = reader.ReadUInt32(); uint num15 = reader.ReadUInt32(); uint num16 = reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.BaseStream.Seek((long)num14, SeekOrigin.Begin); string[] strArray1 = AudioEngine.readNullTerminatedStrings(count1, reader); this.categories = new AudioCategory[(IntPtr)count1]; reader.BaseStream.Seek((long)num10, SeekOrigin.Begin); for (int index = 0; (long)index < (long)count1; ++index) { this.categories[index] = new AudioCategory(this, strArray1[index], reader); this.categoryLookup.Add(strArray1[index], index); } reader.BaseStream.Seek((long)num15, SeekOrigin.Begin); string[] strArray2 = AudioEngine.readNullTerminatedStrings(count2, reader); this.variables = new AudioEngine.Variable[(IntPtr)count2]; reader.BaseStream.Seek((long)num11, SeekOrigin.Begin); for (int index = 0; (long)index < (long)count2; ++index) { this.variables[index].name = strArray2[index]; byte num17 = reader.ReadByte(); this.variables[index].isPublic = ((int)num17 & 1) != 0; this.variables[index].isReadOnly = ((int)num17 & 2) != 0; this.variables[index].isGlobal = ((int)num17 & 4) == 0; this.variables[index].isReserved = ((int)num17 & 8) != 0; this.variables[index].initValue = reader.ReadSingle(); this.variables[index].minValue = reader.ReadSingle(); this.variables[index].maxValue = reader.ReadSingle(); this.variables[index].value = this.variables[index].initValue; this.variableLookup.Add(strArray2[index], index); } this.rpcCurves = new AudioEngine.RpcCurve[(IntPtr)num7]; reader.BaseStream.Seek((long)num16, SeekOrigin.Begin); for (int index1 = 0; (long)index1 < (long)num7; ++index1) { this.rpcCurves[index1].variable = (int)reader.ReadUInt16(); int length = (int)reader.ReadByte(); this.rpcCurves[index1].parameter = (AudioEngine.RpcParameter)reader.ReadUInt16(); this.rpcCurves[index1].points = new AudioEngine.RpcPoint[length]; for (int index2 = 0; index2 < length; ++index2) { this.rpcCurves[index1].points[index2].x = reader.ReadSingle(); this.rpcCurves[index1].points[index2].y = reader.ReadSingle(); this.rpcCurves[index1].points[index2].type = (AudioEngine.RpcPointType)reader.ReadByte(); } } } } }
internal Cue( AudioEngine audioEngine, List <string> waveBankNames, string name, CueData data, bool managed ) { INTERNAL_baseEngine = audioEngine; INTERNAL_waveBankNames = waveBankNames; Name = name; INTERNAL_data = data; IsPrepared = false; IsPreparing = true; INTERNAL_maxRpcReleaseTime = 0; foreach (XACTSound curSound in data.Sounds) { /* Determine the release times per track, if any, to be used to extend * the sound when playing the release. */ { ushort maxReleaseMS = 0; // Loop over tracks. for (int i = 0; i < curSound.RPCCodes.Count; i += 1) { // Loop over curves. foreach (uint curCode in curSound.RPCCodes[i]) { RPC curRPC = INTERNAL_baseEngine.INTERNAL_getRPC(curCode); if (!INTERNAL_baseEngine.INTERNAL_isGlobalVariable(curRPC.Variable)) { // Only release times applied to volume are considered. if (curRPC.Variable.Equals("ReleaseTime") && curRPC.Parameter == RPCParameter.Volume) { maxReleaseMS = Math.Max((ushort)curRPC.LastPoint.X, maxReleaseMS); } } } } // Keep track of the maximum release time to extend the sound. INTERNAL_maxRpcReleaseTime = maxReleaseMS; } } IsPrepared = true; IsPreparing = false; IsStopped = false; INTERNAL_isManaged = managed; INTERNAL_category = INTERNAL_baseEngine.INTERNAL_initCue( this, data.Category ); eventVolume = 0.0; eventPitch = 0.0f; INTERNAL_userControlledPlaying = false; INTERNAL_isPositional = false; INTERNAL_playWaveEventBySound = new Dictionary <SoundEffectInstance, PlayWaveEventInstance>(); INTERNAL_timer = new Stopwatch(); INTERNAL_instancePool = new List <SoundEffectInstance>(); INTERNAL_instanceVolumes = new List <double>(); INTERNAL_instancePitches = new List <short>(); INTERNAL_rpcTrackVolumes = new List <float>(); INTERNAL_rpcTrackPitches = new List <float>(); }
/// <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) { filename = FileHelpers.NormalizeFilePathSeparators(fileName); audioengine = audioEngine; }
public void Play(float volume, AudioEngine engine) { _cueVolume = volume; var category = engine.Categories[_categoryID]; var curInstances = category.GetPlayingInstanceCount(); if (curInstances >= category.maxInstances) { var prevSound = category.GetOldestInstance(); if (prevSound != null) { prevSound.SetFade(0.0f, category.fadeOut); prevSound.Stop(AudioStopOptions.Immediate); SetFade(category.fadeIn, 0.0f); } } float finalVolume = _volume * _cueVolume * category._volume[0]; float finalPitch = _pitch + _cuePitch; float finalMix = _useReverb ? _cueReverbMix : 0.0f; if (_complexSound) { foreach (XactClip clip in _soundClips) { clip.UpdateState(finalVolume, finalPitch, finalMix, _cueFilterFrequency, _cueFilterQFactor); clip.Play(); } } else { if (_wave != null) { if (_streaming) { _wave.Dispose(); } else { _wave._isXAct = false; } _wave = null; } _wave = _soundBank.GetSoundEffectInstance(_waveBankIndex, _trackIndex, out _streaming); if (_wave == null) { // We couldn't create a sound effect instance, most likely // because we've reached the sound pool limits. return; } _wave.Pitch = finalPitch; _wave.Volume = finalVolume; _wave.PlatformSetReverbMix(finalMix); _wave.Play(); } }
/// <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 } } } }
/// <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); } } } } }
public WaveBank(AudioEngine audioEngine, string nonStreamingWaveBankFilename) { WaveBank.WaveBankData waveBankData; waveBankData.EntryNameElementSize = 0; waveBankData.CompactFormat = 0; waveBankData.Alignment = 0; WaveBank.WaveBankEntry waveBankEntry; waveBankEntry.Format = 0; waveBankEntry.PlayRegion.Length = 0; waveBankEntry.PlayRegion.Offset = 0; int num1 = 0; nonStreamingWaveBankFilename = nonStreamingWaveBankFilename.Replace('\\', Path.DirectorySeparatorChar); BinaryReader binaryReader = new BinaryReader((Stream) new FileStream(nonStreamingWaveBankFilename, FileMode.Open)); binaryReader.ReadBytes(4); WaveBank.WaveBankHeader waveBankHeader; waveBankHeader.Version = binaryReader.ReadInt32(); int index1 = 4; if (waveBankHeader.Version <= 3) { index1 = 3; } if (waveBankHeader.Version >= 42) { binaryReader.ReadInt32(); } waveBankHeader.Segments = new WaveBank.Segment[5]; for (int index2 = 0; index2 <= index1; ++index2) { waveBankHeader.Segments[index2].Offset = binaryReader.ReadInt32(); waveBankHeader.Segments[index2].Length = binaryReader.ReadInt32(); } binaryReader.BaseStream.Seek((long)waveBankHeader.Segments[0].Offset, SeekOrigin.Begin); waveBankData.Flags = binaryReader.ReadInt32(); waveBankData.EntryCount = binaryReader.ReadInt32(); int num2 = waveBankHeader.Version == 2 ? 0 : (waveBankHeader.Version != 3 ? 1 : 0); waveBankData.BankName = num2 != 0 ? Encoding.UTF8.GetString(binaryReader.ReadBytes(64)).Replace("\0", "") : Encoding.UTF8.GetString(binaryReader.ReadBytes(16)).Replace("\0", ""); this.BankName = waveBankData.BankName; if (waveBankHeader.Version == 1) { waveBankData.EntryMetaDataElementSize = 20; } else { waveBankData.EntryMetaDataElementSize = binaryReader.ReadInt32(); waveBankData.EntryNameElementSize = binaryReader.ReadInt32(); waveBankData.Alignment = binaryReader.ReadInt32(); num1 = waveBankHeader.Segments[1].Offset; } if ((waveBankData.Flags & 131072) != 0) { binaryReader.ReadInt32(); } int num3 = waveBankHeader.Segments[index1].Offset; if (num3 == 0) { num3 = num1 + waveBankData.EntryCount * waveBankData.EntryMetaDataElementSize; } int index3 = 2; if (waveBankHeader.Version >= 42) { index3 = 3; } int num4 = waveBankHeader.Segments[index3].Offset; if (waveBankHeader.Segments[index3].Offset != 0 && waveBankHeader.Segments[index3].Length != 0) { if (waveBankData.EntryNameElementSize == -1) { waveBankData.EntryNameElementSize = 0; } new byte[waveBankData.EntryNameElementSize + 1][waveBankData.EntryNameElementSize] = (byte)0; } this.sounds = new SoundEffectInstance[waveBankData.EntryCount]; for (int index2 = 0; index2 < waveBankData.EntryCount; ++index2) { binaryReader.BaseStream.Seek((long)num1, SeekOrigin.Begin); if ((waveBankData.Flags & 131072) != 0) { int num5 = binaryReader.ReadInt32(); waveBankEntry.Format = waveBankData.CompactFormat; waveBankEntry.PlayRegion.Offset = (num5 & 2097151) * waveBankData.Alignment; waveBankEntry.PlayRegion.Length = num5 >> 21 & 2047; binaryReader.BaseStream.Seek((long)(num1 + waveBankData.EntryMetaDataElementSize), SeekOrigin.Begin); int num6 = index2 != waveBankData.EntryCount - 1 ? (binaryReader.ReadInt32() & 2097151) * waveBankData.Alignment : waveBankHeader.Segments[index1].Length; waveBankEntry.PlayRegion.Length = num6 - waveBankEntry.PlayRegion.Offset; } else { if (waveBankHeader.Version == 1) { waveBankEntry.Format = binaryReader.ReadInt32(); waveBankEntry.PlayRegion.Offset = binaryReader.ReadInt32(); waveBankEntry.PlayRegion.Length = binaryReader.ReadInt32(); waveBankEntry.LoopRegion.Offset = binaryReader.ReadInt32(); waveBankEntry.LoopRegion.Length = binaryReader.ReadInt32(); } else { if (waveBankData.EntryMetaDataElementSize >= 4) { waveBankEntry.FlagsAndDuration = binaryReader.ReadInt32(); } if (waveBankData.EntryMetaDataElementSize >= 8) { waveBankEntry.Format = binaryReader.ReadInt32(); } if (waveBankData.EntryMetaDataElementSize >= 12) { waveBankEntry.PlayRegion.Offset = binaryReader.ReadInt32(); } if (waveBankData.EntryMetaDataElementSize >= 16) { waveBankEntry.PlayRegion.Length = binaryReader.ReadInt32(); } if (waveBankData.EntryMetaDataElementSize >= 20) { waveBankEntry.LoopRegion.Offset = binaryReader.ReadInt32(); } if (waveBankData.EntryMetaDataElementSize >= 24) { waveBankEntry.LoopRegion.Length = binaryReader.ReadInt32(); } } if (waveBankData.EntryMetaDataElementSize < 24 && waveBankEntry.PlayRegion.Length != 0) { waveBankEntry.PlayRegion.Length = waveBankHeader.Segments[index1].Length; } } num1 += waveBankData.EntryMetaDataElementSize; waveBankEntry.PlayRegion.Offset += num3; int num7; int num8; int num9; int num10; int num11; if (waveBankHeader.Version == 1) { num7 = waveBankEntry.Format & 1; num8 = waveBankEntry.Format >> 1 & 7; num9 = waveBankEntry.Format >> 5 & 262143; num10 = waveBankEntry.Format >> 23 & (int)byte.MaxValue; num11 = waveBankEntry.Format >> 31 & 1; } else { num7 = waveBankEntry.Format & 3; num8 = waveBankEntry.Format >> 2 & 7; num9 = waveBankEntry.Format >> 5 & 262143; num10 = waveBankEntry.Format >> 23 & (int)byte.MaxValue; num11 = waveBankEntry.Format >> 31 & 1; } binaryReader.BaseStream.Seek((long)waveBankEntry.PlayRegion.Offset, SeekOrigin.Begin); byte[] buffer = binaryReader.ReadBytes(waveBankEntry.PlayRegion.Length); if (num7 == 0) { MemoryStream memoryStream = new MemoryStream(44 + buffer.Length); BinaryWriter binaryWriter = new BinaryWriter((Stream)memoryStream); binaryWriter.Write("RIFF".ToCharArray()); binaryWriter.Write(36 + buffer.Length); binaryWriter.Write("WAVE".ToCharArray()); binaryWriter.Write("fmt ".ToCharArray()); binaryWriter.Write(16); binaryWriter.Write((short)1); binaryWriter.Write((short)num8); binaryWriter.Write(num9); binaryWriter.Write(num9 * num10); binaryWriter.Write((short)num10); if (num11 == 1) { binaryWriter.Write((short)16); } else { binaryWriter.Write((short)8); } binaryWriter.Write("data".ToCharArray()); binaryWriter.Write(buffer.Length); binaryWriter.Write(buffer); binaryWriter.Close(); memoryStream.Close(); this.sounds[index2] = new SoundEffect((string)null, memoryStream.ToArray()).CreateInstance(false); } else { if (num7 != 3) { throw new NotImplementedException(); } byte[] numArray1 = new byte[16] { (byte)48, (byte)38, (byte)178, (byte)117, (byte)142, (byte)102, (byte)207, (byte)17, (byte)166, (byte)217, (byte)0, (byte)170, (byte)0, (byte)98, (byte)206, (byte)108 }; bool flag1 = true; for (int index4 = 0; index4 < numArray1.Length; ++index4) { if ((int)numArray1[index4] != (int)buffer[index4]) { flag1 = false; break; } } byte[][] numArray2 = new byte[2][] { new byte[16] { (byte)0, (byte)0, (byte)0, (byte)24, (byte)102, (byte)116, (byte)121, (byte)112, (byte)77, (byte)52, (byte)65, (byte)32, (byte)0, (byte)0, (byte)2, (byte)0 }, new byte[16] { (byte)0, (byte)0, (byte)0, (byte)32, (byte)102, (byte)116, (byte)121, (byte)112, (byte)77, (byte)52, (byte)65, (byte)32, (byte)0, (byte)0, (byte)0, (byte)0 } }; bool flag2 = false; for (int index4 = 0; index4 < numArray2.Length; ++index4) { byte[] numArray3 = numArray2[index4]; bool flag3 = true; for (int index5 = 0; index5 < numArray3.Length; ++index5) { if ((int)numArray3[index5] != (int)buffer[index5]) { flag3 = false; break; } } if (flag3) { flag2 = true; break; } } if (!flag1 && !flag2) { throw new NotImplementedException(); } string str = Path.GetTempFileName(); if (flag1) { str = str.Replace(".tmp", ".wma"); } else if (flag2) { str = str.Replace(".tmp", ".m4a"); } using (FileStream fileStream = File.Create(str)) fileStream.Write(buffer, 0, buffer.Length); this.sounds[index2] = new SoundEffect(str).CreateInstance(false); } } audioEngine.Wavebanks[this.BankName] = this; }
/// <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; }
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; }
public WaveBank(AudioEngine audioEngine, string 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; #if WINRT const char notSeparator = '/'; const char separator = '\\'; #else const char notSeparator = '\\'; var separator = Path.DirectorySeparatorChar; #endif // Check for windows-style directory separator character nonStreamingWaveBankFilename = nonStreamingWaveBankFilename.Replace(notSeparator, separator); #if !ANDROID BinaryReader reader = new BinaryReader(TitleContainer.OpenStream(nonStreamingWaveBankFilename)); #else Stream stream = Game.Activity.Assets.Open(nonStreamingWaveBankFilename); MemoryStream ms = new MemoryStream(); stream.CopyTo(ms); stream.Close(); ms.Position = 0; BinaryReader reader = new BinaryReader(ms); #endif 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 SoundEffectInstance[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 int 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 = (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 = (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); if (codec == MiniFormatTag_PCM) { //write PCM data into a wav #if DIRECTX SharpDX.Multimedia.WaveFormat waveFormat = new SharpDX.Multimedia.WaveFormat(rate, chans); sounds[current_entry] = new SoundEffect(waveFormat, audiodata, 0, audiodata.Length, wavebankentry.LoopRegion.Offset, wavebankentry.LoopRegion.Length).CreateInstance(); #else sounds[current_entry] = new SoundEffectInstance(audiodata, rate, chans); #endif } else if (codec == MiniForamtTag_WMA) //WMA or xWMA (or XMA2) { byte[] wmaSig = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x0, 0xaa, 0x0, 0x62, 0xce, 0x6c }; bool isWma = true; for (int i = 0; i < wmaSig.Length; i++) { if (wmaSig[i] != audiodata[i]) { isWma = false; break; } } //Let's support m4a data as well for convenience byte[][] m4aSigs = new byte[][] { new byte[] { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20, 0x00, 0x00, 0x02, 0x00 }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20, 0x00, 0x00, 0x00, 0x00 } }; bool isM4a = false; for (int i = 0; i < m4aSigs.Length; i++) { byte[] sig = m4aSigs[i]; bool matches = true; for (int j = 0; j < sig.Length; j++) { if (sig[j] != audiodata[j]) { matches = false; break; } } if (matches) { isM4a = true; break; } } if (isWma || isM4a) { //WMA data can sometimes be played directly #if DIRECTX throw new NotImplementedException(); #elif !WINRT //hack - NSSound can't play non-wav from data, we have to give a filename string filename = Path.GetTempFileName(); if (isWma) { filename = filename.Replace(".tmp", ".wma"); } else if (isM4a) { filename = filename.Replace(".tmp", ".m4a"); } using (var audioFile = File.Create(filename)) audioFile.Write(audiodata, 0, audiodata.Length); sounds[current_entry] = new SoundEffect(filename).CreateInstance(); #else throw new NotImplementedException(); #endif } else { //An xWMA or XMA2 file. Can't be played atm :( throw new NotImplementedException(); } #if !DIRECTX /* DirectX platforms can use XAudio2 to stream MSADPCM natively. * This code is cross-platform, but the problem is that it just * decodes ALL of the wavedata here. For XAudio2 in particular, * this is probably ludicrous. * * You need to write a DIRECTX ADPCM reader that just loads this * into the SoundEffect. No decoding should be necessary. * -flibit */ } else if (codec == MiniFormatTag_ADPCM) { using (MemoryStream dataStream = new MemoryStream(audiodata)) { using (BinaryReader source = new BinaryReader(dataStream)) { sounds[current_entry] = new SoundEffectInstance( MSADPCMToPCM.MSADPCM_TO_PCM(source, (short)chans, (short)align), rate, chans ); } } #endif } else { throw new NotImplementedException(); } } audioEngine.Wavebanks[BankName] = this; }
/// <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) : this(audioEngine, nonStreamingWaveBankFilename, false, 0, 0) { }
/// <param name="audioEngine">Instance of the AudioEngine to associate this wave bank with.</param> /// <param name="streamingWaveBankFilename">Path to the .xwb to stream from.</param> /// <param name="offset">DVD sector-aligned offset within the wave bank data file.</param> /// <param name="packetsize">Stream packet size, in sectors, to use for each stream. The minimum value is 2.</param> /// <remarks> /// <para>This constructor streams wave data as needed.</para> /// <para>Note that packetsize is in sectors, which is 2048 bytes.</para> /// <para>AudioEngine.Update() must be called at least once before using data from a streaming wave bank.</para> /// </remarks> public WaveBank(AudioEngine audioEngine, string streamingWaveBankFilename, int offset, short packetsize) : this(audioEngine, streamingWaveBankFilename, true, offset, packetsize) { }
public WaveBank(AudioEngine audioEngine, string 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; wavebankentry.Format = 0; wavebankentry.PlayRegion.Length = 0; wavebankentry.PlayRegion.Offset = 0; int wavebank_offset = 0; // Check for windows-style directory separator character nonStreamingWaveBankFilename = nonStreamingWaveBankFilename.Replace('\\', Path.DirectorySeparatorChar); BinaryReader reader = new BinaryReader(new FileStream(nonStreamingWaveBankFilename, FileMode.Open)); 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)).Replace("\0", ""); } else { wavebankdata.BankName = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(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 } int compact_format; if ((wavebankdata.Flags & Flag_Compact) != 0) { compact_format = reader.ReadInt32(); } 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; } int waveentry_offset = wavebankheader.Segments[segidx_entry_name].Offset; 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 SoundEffectInstance[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)); 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 int 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 = (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 = (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); if (codec == MiniFormatTag_PCM) { //write PCM data into a wav MemoryStream mStream = new MemoryStream(44 + audiodata.Length); BinaryWriter writer = new BinaryWriter(mStream); writer.Write("RIFF".ToCharArray()); writer.Write((int)(36 + audiodata.Length)); writer.Write("WAVE".ToCharArray()); writer.Write("fmt ".ToCharArray()); writer.Write((int)16); //header size writer.Write((short)1); //format (PCM) writer.Write((short)chans); writer.Write((int)rate); //sample rate writer.Write((int)rate * align); //byte rate writer.Write((short)align); if (bits == 1) { writer.Write((short)16); } else { writer.Write((short)8); //not sure if this is right } writer.Write("data".ToCharArray()); writer.Write((int)audiodata.Length); writer.Write(audiodata); writer.Close(); mStream.Close(); sounds[current_entry] = new SoundEffect(mStream.ToArray(), rate, AudioChannels.Mono).CreateInstance(); } else if (codec == MiniForamtTag_WMA) //WMA or xWMA (or XMA2) { byte[] wmaSig = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x0, 0xaa, 0x0, 0x62, 0xce, 0x6c }; bool isWma = true; for (int i = 0; i < wmaSig.Length; i++) { if (wmaSig[i] != audiodata[i]) { isWma = false; break; } } //Let's support m4a data as well for convenience byte[][] m4aSigs = new byte[][] { new byte[] { 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20, 0x00, 0x00, 0x02, 0x00 }, new byte[] { 0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20, 0x00, 0x00, 0x00, 0x00 } }; bool isM4a = false; for (int i = 0; i < m4aSigs.Length; i++) { byte[] sig = m4aSigs[i]; bool matches = true; for (int j = 0; j < sig.Length; j++) { if (sig[j] != audiodata[j]) { matches = false; break; } } if (matches) { isM4a = true; break; } } if (isWma || isM4a) { //WMA data can sometimes be played directly //hack - NSSound can't play non-wav from data, we have to give a filename string filename = Path.GetTempFileName(); if (isWma) { filename = filename.Replace(".tmp", ".wma"); } else if (isM4a) { filename = filename.Replace(".tmp", ".m4a"); } FileStream audioFile = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite); audioFile.Write(audiodata, 0, audiodata.Length); audioFile.Close(); sounds[current_entry] = new SoundEffect(filename).CreateInstance(); } else { //An xWMA or XMA2 file. Can't be played atm :( throw new NotImplementedException(); } } else { throw new NotImplementedException(); } } audioEngine.Wavebanks[BankName] = this; }
// get some new randomness in this sucker public void Reroll() { try { // new sound instance plz _sound = null; int totWeight = 0; for (int i = 0; i < mData.mEntries.Length; i++) { totWeight += mData.mEntries[i]._weight; } int weight = 0; switch (mData.mVariation) { case 0: //kOrdered mData.currIdx++; if (mData.currIdx >= mData.mEntries.Length) { mData.currIdx = 0; } break; case 2: //kRandom weight = GSGE.RandomMath.RandomInt(totWeight); totWeight = 0; mData.currIdx = 0; for (int i = 0; i < mData.mEntries.Length; i++) { totWeight += mData.mEntries[i]._weight; if (weight < totWeight) { mData.currIdx = i; break; } } break; case 3: //kRandomNoImmediateRepeat if (mData.currIdx >= 0 && mData.currIdx < mData.mEntries.Length) { totWeight -= mData.mEntries[mData.currIdx]._weight; } else { mData.currIdx = 0; } weight = GSGE.RandomMath.RandomInt(totWeight); totWeight = 0; for (int i = 0; i < mData.mEntries.Length; i++) { if (i == mData.currIdx) { continue; } totWeight += mData.mEntries[i]._weight; if (weight < totWeight) { mData.currIdx = i; break; } } break; case 4: //kShuffle mData.shuffleIdx++; if (mData.shuffleIdx >= mData.mEntries.Length) { mData.shuffleIdx = 0; int i; // reorder next random set List <int> ls = new List <int>(); for (i = 0; i < mData.mEntries.Length; i++) { ls.Add(i); } i = 0; while (ls.Count > 0) { int idx = GSGE.RandomMath.RandomInt(ls.Count); mData.shuffle[i] = ls[idx]; ls.RemoveAt(idx); i++; } } mData.currIdx = mData.shuffle[mData.shuffleIdx]; break; default: throw new NotImplementedException(); } } catch (Exception) { mData.currIdx = 0; } if (0 <= mData.currIdx && mData.currIdx < mData.mEntries.Length) { PlayWaveHelper pwh = mData.mEntries[mData.currIdx]; AudioEngine audioengine = AudioManager.GetAudioManager().GetAudioEngine(); foreach (WaveBank wavebank in audioengine.Wavebanks) { if (wavebank.IsLoaded && wavebank.BankName == pwh._bankname) { if (0 <= pwh._index && wavebank.mSounds.Length > pwh._index) { SoundData sd = wavebank.mSounds[pwh._index]; sd.Looping = mData.mLoopCount == 255; _sound = new Sound(sd); } break; } } //GSGE.Debug.assert(_sound != null); mVolVar = RandomMath.RandomBetween(mData.mVolumeVariationMin, mData.mVolumeVariationMax) + mData.mVolume; mPitchVar = RandomMath.RandomBetween(mData.mPitchVariationMin, mData.mPitchVariationMax); } }
public void Dispose(AudioEngine audioEngine, List <string> waveBankNames) { Clips.Clear(); Sound.DisposeInstance(this, audioEngine, waveBankNames); }
public SoundBank(AudioEngine audioEngine, string fileName) { this.filename = fileName.Replace('\\', Path.DirectorySeparatorChar); this.audioengine = audioEngine; }
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; }
public XactSound(AudioEngine engine, SoundBank soundBank, BinaryReader soundReader) { _soundBank = soundBank; var flags = soundReader.ReadByte(); _complexSound = (flags & 0x1) != 0; var hasRPCs = (flags & 0x0E) != 0; var hasDSPs = (flags & 0x10) != 0; _categoryID = soundReader.ReadUInt16(); _volume = XactHelpers.ParseVolumeFromDecibels(soundReader.ReadByte()); _pitch = soundReader.ReadInt16() / 1000.0f; soundReader.ReadByte(); //priority soundReader.ReadUInt16(); // filter stuff? var numClips = 0; if (_complexSound) { numClips = soundReader.ReadByte(); } else { _trackIndex = soundReader.ReadUInt16(); _waveBankIndex = soundReader.ReadByte(); } if (!hasRPCs) { RpcCurves = new int[0]; } else { var current = soundReader.BaseStream.Position; // This doesn't seem to be used... might have been there // to allow for some future file format expansion. var dataLength = soundReader.ReadUInt16(); var numPresets = soundReader.ReadByte(); RpcCurves = new int[numPresets]; for (var i = 0; i < numPresets; i++) { RpcCurves[i] = engine.GetRpcIndex(soundReader.ReadUInt32()); } // Just in case seek to the right spot. soundReader.BaseStream.Seek(current + dataLength, SeekOrigin.Begin); } if (!hasDSPs) { _useReverb = false; } else { // The file format for this seems to follow the pattern for // the RPC curves above, but in this case XACT only supports // a single effect... Microsoft Reverb... so just set it. _useReverb = true; soundReader.BaseStream.Seek(7, SeekOrigin.Current); } if (_complexSound) { _soundClips = new XactClip[numClips]; for (int i = 0; i < numClips; i++) { _soundClips[i] = new XactClip(soundBank, soundReader, _useReverb); } } var category = engine.Categories[_categoryID]; category.AddSound(this); }
public static void Initialize() { // Initialize audio objects. engine = new AudioEngine(@"Content/sound/tglrf.xgs"); soundBank = new SoundBank(engine, @"Content/sound/Sound Bank.xsb"); waveBank = new WaveBank(engine, @"Content/sound/Wave Bank.xwb"); }