private void LoadWaveEntry(SoundStreamEntry entry, ushort track, BinaryReader reader) { // Read Wavedata reader.BaseStream.Seek(entry.PlayOffset, SeekOrigin.Begin); byte[] entryData = reader.ReadBytes((int)entry.PlayLength); // Load SoundEffect based on codec if (entry.Codec == 0x0) // PCM { INTERNAL_sounds[track] = new SoundEffect( "WaveBank Sound", entryData, entry.Frequency, entry.Channels, entry.LoopOffset, entry.LoopLength, false, entry.BitDepth ); } else if (entry.Codec == 0x2) // ADPCM { INTERNAL_sounds[track] = new SoundEffect( "WaveBank Sound", entryData, entry.Frequency, entry.Channels, entry.LoopOffset, entry.LoopLength, true, (entry.Alignment + 16) * 2 ); } else // Includes 0x1 - XMA, 0x3 - WMA { throw new NotSupportedException("Rebuild your WaveBanks with ADPCM!"); } }
private void LoadWaveEntry(SoundStreamEntry entry, ushort track, BinaryReader reader) { // Read Wavedata reader.BaseStream.Seek(entry.PlayOffset, SeekOrigin.Begin); byte[] entryData = reader.ReadBytes((int) entry.PlayLength); // Load SoundEffect based on codec if (entry.Codec == 0x0) // PCM { INTERNAL_sounds[track] = new SoundEffect( "WaveBank Sound", entryData, entry.Frequency, entry.Channels, entry.LoopOffset, entry.LoopLength, false, entry.BitDepth ); } else if (entry.Codec == 0x2) // ADPCM { INTERNAL_sounds[track] = new SoundEffect( "WaveBank Sound", entryData, entry.Frequency, entry.Channels, entry.LoopOffset, entry.LoopLength, true, (entry.Alignment + 16) * 2 ); } else // Includes 0x1 - XMA, 0x3 - WMA { throw new NotSupportedException(); } }
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; }
private void LoadWaveBank(AudioEngine audioEngine, BinaryReader reader, bool streaming) { /* Until we finish the LoadWaveBank process, this WaveBank is NOT * ready to run. For us this doesn't really matter, but the game * could be loading WaveBanks asynchronously, so let's be careful. * -flibit */ IsPrepared = false; INTERNAL_baseEngine = audioEngine; // Check the file header. Should be 'WBND' if (reader.ReadUInt32() != 0x444E4257) { throw new ArgumentException("WBND format not recognized!"); } // Check the content version. Assuming XNA4 Refresh. if (reader.ReadUInt32() != AudioEngine.ContentVersion) { throw new ArgumentException("WBND Content version!"); } // Check the tool version. Assuming XNA4 Refresh. if (reader.ReadUInt32() != 44) { throw new ArgumentException("WBND Tool version!"); } // Obtain WaveBank chunk offsets/lengths uint[] offsets = new uint[5]; uint[] lengths = new uint[5]; for (int i = 0; i < 5; i += 1) { offsets[i] = reader.ReadUInt32(); lengths[i] = reader.ReadUInt32(); } // Seek to the first offset, obtain WaveBank info reader.BaseStream.Seek(offsets[0], SeekOrigin.Begin); // Unknown value, IsStreaming bool? reader.ReadUInt16(); // WaveBank Flags ushort wavebankFlags = reader.ReadUInt16(); // bool containsEntryNames = (wavebankFlags & 0x00010000) != 0; bool compact = (wavebankFlags & 0x00020000) != 0; // bool syncDisabled = (wavebankFlags & 0x00040000) != 0; // bool containsSeekTables = (wavebankFlags & 0x00080000) != 0; // WaveBank Entry Count uint numEntries = reader.ReadUInt32(); // WaveBank Name INTERNAL_name = System.Text.Encoding.UTF8.GetString( reader.ReadBytes(64), 0, 64 ).Replace("\0", ""); // WaveBank entry information uint metadataElementSize = reader.ReadUInt32(); reader.ReadUInt32(); // nameElementSize uint alignment = reader.ReadUInt32(); // Determine the generic play region offset uint playRegionOffset = offsets[4]; if (playRegionOffset == 0) { playRegionOffset = offsets[1] + (numEntries * metadataElementSize); } // Entry format. Read early for Compact data uint entryFormat = 0; if (compact) { entryFormat = reader.ReadUInt32(); } // Read in the wavedata INTERNAL_sounds = new SoundEffect[numEntries]; if (streaming) { INTERNAL_soundStreamEntries = new SoundStreamEntry[numEntries]; } uint curOffset = offsets[1]; for (int curEntry = 0; curEntry < numEntries; curEntry += 1) { // Seek to the current entry reader.BaseStream.Seek(curOffset, SeekOrigin.Begin); // Entry Information uint entryPlayOffset = 0; uint entryPlayLength = 0; uint entryLoopOffset = 0; uint entryLoopLength = 0; // Obtain Entry Information if (compact) { uint entryLength = reader.ReadUInt32(); entryPlayOffset = (entryLength & ((1 << 21) - 1)) * alignment; entryPlayLength = (entryLength >> 21) & ((1 << 11) - 1); // FIXME: Deviation Length reader.BaseStream.Seek( curOffset + metadataElementSize, SeekOrigin.Begin ); if (curEntry == (numEntries - 1)) { // Last track, last length. entryLength = lengths[4]; } else { entryLength = ( ( reader.ReadUInt32() & ((1 << 21) - 1) ) * alignment ); } entryPlayLength = entryLength - entryPlayOffset; } else { if (metadataElementSize >= 4) reader.ReadUInt32(); // Flags/Duration, unused if (metadataElementSize >= 8) entryFormat = reader.ReadUInt32(); if (metadataElementSize >= 12) entryPlayOffset = reader.ReadUInt32(); if (metadataElementSize >= 16) entryPlayLength = reader.ReadUInt32(); if (metadataElementSize >= 20) entryLoopOffset = reader.ReadUInt32(); if (metadataElementSize >= 24) entryLoopLength = reader.ReadUInt32(); else { // FIXME: This is a bit hacky. if (entryPlayLength != 0) { entryPlayLength = lengths[4]; } } } // Update seek offsets curOffset += metadataElementSize; entryPlayOffset += playRegionOffset; // Parse Format for Wavedata information uint entryCodec = (entryFormat >> 0) & ((1 << 2) - 1); uint entryChannels = (entryFormat >> 2) & ((1 << 3) - 1); uint entryFrequency = (entryFormat >> (2 + 3)) & ((1 << 18) - 1); uint entryAlignment = (entryFormat >> (2 + 3 + 18)) & ((1 << 8) - 1); uint entryBitDepth = (entryFormat >> (2 + 3 + 18 + 8)); if (streaming) { INTERNAL_soundStreamEntries[curEntry] = new SoundStreamEntry( entryPlayOffset, entryPlayLength, entryCodec, entryFrequency, entryChannels, entryLoopOffset, entryLoopLength, entryAlignment, entryBitDepth ); } else { SoundStreamEntry filler = new SoundStreamEntry( entryPlayOffset, entryPlayLength, entryCodec, entryFrequency, entryChannels, entryLoopOffset, entryLoopLength, entryAlignment, entryBitDepth ); LoadWaveEntry(filler, (ushort) curEntry, reader); } } // Add this WaveBank to the AudioEngine Dictionary audioEngine.INTERNAL_addWaveBank(INTERNAL_name, this); // Finally. IsDisposed = false; IsPrepared = true; }