private void PlatformInitializeFormat(byte[] header, byte[] buffer, int bufferSize, int loopStart, int loopLength) { var format = BitConverter.ToInt16(header, 0); var channels = BitConverter.ToInt16(header, 2); var sampleRate = BitConverter.ToInt32(header, 4); var blockAlignment = BitConverter.ToInt32(header, 12); // We need to decode MSADPCM. var supportsADPCM = OpenALSoundController.GetInstance.SupportsADPCM; if (format == 2 && !supportsADPCM) { using (var stream = new MemoryStream(buffer)) using (var reader = new BinaryReader(stream)) { buffer = MSADPCMToPCM.MSADPCM_TO_PCM(reader, (short)channels, (short)blockAlignment); format = 1; } } if (!supportsADPCM && format != 1) { throw new NotSupportedException("Unsupported wave format!"); } if (supportsADPCM && format == 2) { PlatformInitializeAdpcm(buffer, 0, buffer.Length, sampleRate, (AudioChannels)channels, blockAlignment, loopStart, loopLength); } else { PlatformInitializePcm(buffer, 0, buffer.Length, sampleRate, (AudioChannels)channels, loopStart, loopLength); } }
private void INTERNAL_decodeADPCM(object obj) { ADPCMContainer adpcm = (ADPCMContainer)obj; using (MemoryStream dataStream = new MemoryStream(adpcm.adpcmData)) { using (BinaryReader source = new BinaryReader(dataStream)) { sounds[adpcm.effectIndex] = new SoundEffect( MSADPCMToPCM.MSADPCM_TO_PCM(source, adpcm.channels, adpcm.blockAlign), adpcm.sampleRate, (AudioChannels)adpcm.channels ); } } }
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(); waveBankData.BankName = waveBankHeader.Version == 2 || waveBankHeader.Version == 3 ? Encoding.UTF8.GetString(binaryReader.ReadBytes(16)).Replace("\0", "") : Encoding.UTF8.GetString(binaryReader.ReadBytes(64)).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 num2 = waveBankHeader.Segments[index1].Offset; if (num2 == 0) { num2 = num1 + waveBankData.EntryCount * waveBankData.EntryMetaDataElementSize; } int index3 = 2; if (waveBankHeader.Version >= 42) { index3 = 3; } int num3 = 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 num4 = binaryReader.ReadInt32(); waveBankEntry.Format = waveBankData.CompactFormat; waveBankEntry.PlayRegion.Offset = (num4 & 2097151) * waveBankData.Alignment; waveBankEntry.PlayRegion.Length = num4 >> 21 & 2047; binaryReader.BaseStream.Seek((long)(num1 + waveBankData.EntryMetaDataElementSize), SeekOrigin.Begin); int num5 = index2 != waveBankData.EntryCount - 1 ? (binaryReader.ReadInt32() & 2097151) * waveBankData.Alignment : waveBankHeader.Segments[index1].Length; waveBankEntry.PlayRegion.Length = num5 - 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 += num2; int num6; int num7; int sampleRate; int num8; int num9; if (waveBankHeader.Version == 1) { num6 = waveBankEntry.Format & 1; num7 = waveBankEntry.Format >> 1 & 7; sampleRate = waveBankEntry.Format >> 5 & 262143; num8 = waveBankEntry.Format >> 23 & (int)byte.MaxValue; num9 = waveBankEntry.Format >> 31 & 1; } else { num6 = waveBankEntry.Format & 3; num7 = waveBankEntry.Format >> 2 & 7; sampleRate = waveBankEntry.Format >> 5 & 262143; num8 = waveBankEntry.Format >> 23 & (int)byte.MaxValue; num9 = waveBankEntry.Format >> 31 & 1; } binaryReader.BaseStream.Seek((long)waveBankEntry.PlayRegion.Offset, SeekOrigin.Begin); byte[] buffer = binaryReader.ReadBytes(waveBankEntry.PlayRegion.Length); if (num6 == 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)num7); binaryWriter.Write(sampleRate); binaryWriter.Write(sampleRate * num8); binaryWriter.Write((short)num8); if (num9 == 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, false, memoryStream.ToArray()).CreateInstance(false); } else if (num6 == 3) { 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); } else { if (num6 != 2) { throw new NotImplementedException(); } MemoryStream memoryStream = new MemoryStream(buffer); BinaryReader Source = new BinaryReader((Stream)memoryStream); this.sounds[index2] = new SoundEffect(MSADPCMToPCM.MSADPCM_TO_PCM(Source, (short)num7, (short)num8), sampleRate, num7 == 1 ? AudioChannels.Mono : AudioChannels.Stereo).CreateInstance(false); Source.Close(); memoryStream.Close(); } } audioEngine.Wavebanks[this.BankName] = this; }
private void INTERNAL_bufferData(byte[] data, int sampleRate, int channels, int loopStart, int loopEnd, int compressionAlign) { // If there's no loopEnd, just assume we're going to the end. if (loopEnd == 0) { loopEnd = data.Length; } this.loopStart = loopStart; this.loopEnd = loopEnd; INTERNAL_duration = TimeSpan.FromSeconds(data.Length / 2 / channels / ((double)sampleRate)); ALFormat format; if (compressionAlign > 0) { if (AL.Get(ALGetString.Extensions).Contains("AL_EXT_MSADPCM")) { if (compressionAlign == 70) { format = (channels == 2) ? ALFormat.StereoMsadpcm128Ext : ALFormat.MonoMsadpcm128Ext; } else if (compressionAlign == 38) { format = (channels == 2) ? ALFormat.StereoMsadpcm64Ext : ALFormat.MonoMsadpcm64Ext; } else { throw new Exception("MSADPCM blockAlign unsupported in AL_EXT_MSADPCM!"); } } else { byte[] newData; using (MemoryStream stream = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(stream)) { newData = MSADPCMToPCM.MSADPCM_TO_PCM( reader, (short)channels, (short)(compressionAlign - 22) ); } } data = newData; format = (channels == 2) ? ALFormat.Stereo16 : ALFormat.Mono16; } } else { format = (channels == 2) ? ALFormat.Stereo16 : ALFormat.Mono16; } int numBuffers = 1; if (loopStart > 0) { numBuffers++; } if (loopEnd < (data.Length / 2 / channels)) { numBuffers++; } buffers = AL.GenBuffers(numBuffers); if (numBuffers == 3) { AL.BufferData( buffers[0], format, data, loopStart * 2 * channels, sampleRate ); byte[] midBuf = new byte[(loopEnd * 2 * channels) - (loopStart * 2 * channels)]; int cur = 0; for (int i = (loopStart * 2 * channels); i < loopEnd * 2 * channels; i++) { midBuf[cur] = data[i]; cur++; } AL.BufferData( buffers[1], format, midBuf, midBuf.Length, sampleRate ); midBuf = new byte[data.Length - (loopEnd * 2 * channels)]; cur = 0; for (int i = (loopEnd * 2 * channels); i < data.Length; i++) { midBuf[cur] = data[i]; cur++; } AL.BufferData( buffers[2], format, midBuf, midBuf.Length, sampleRate ); } else if (numBuffers == 2) { AL.BufferData( buffers[0], format, data, data.Length, sampleRate ); byte[] midBuf = new byte[(loopEnd * 2 * channels) - (loopStart * 2 * channels)]; int cur = 0; for (int i = loopStart * 2 * channels; i < (loopEnd * 2 * channels); i++) { midBuf[cur] = data[i]; cur++; } AL.BufferData( buffers[1], format, midBuf, midBuf.Length, sampleRate ); } else { AL.BufferData( buffers[0], format, data, data.Length, sampleRate ); } }
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; }
public static byte[] MSADPCM_TO_PCM(BinaryReader Source, short numChannels, short blockAlign) { MemoryStream memoryStream = new MemoryStream(); BinaryWriter binaryWriter = new BinaryWriter((Stream)memoryStream); byte[] nibbleBlock = new byte[2]; long num = Source.BaseStream.Length - (long)blockAlign; if ((int)numChannels == 1) { while (Source.BaseStream.Position <= num) { byte predictor = Source.ReadByte(); short delta = Source.ReadInt16(); short sample_1 = Source.ReadInt16(); short sample_2 = Source.ReadInt16(); binaryWriter.Write(sample_2); binaryWriter.Write(sample_1); for (int index1 = 0; index1 < (int)blockAlign + 15; ++index1) { MSADPCMToPCM.getNibbleBlock(Source.ReadByte(), nibbleBlock); for (int index2 = 0; index2 < 2; ++index2) { binaryWriter.Write(MSADPCMToPCM.calculateSample(nibbleBlock[index2], predictor, ref sample_1, ref sample_2, ref delta)); } } } } else if ((int)numChannels == 2) { while (Source.BaseStream.Position <= num) { byte predictor1 = Source.ReadByte(); byte predictor2 = Source.ReadByte(); short delta1 = Source.ReadInt16(); short delta2 = Source.ReadInt16(); short sample_1_1 = Source.ReadInt16(); short sample_1_2 = Source.ReadInt16(); short sample_2_1 = Source.ReadInt16(); short sample_2_2 = Source.ReadInt16(); binaryWriter.Write(sample_2_1); binaryWriter.Write(sample_2_2); binaryWriter.Write(sample_1_1); binaryWriter.Write(sample_1_2); for (int index = 0; index < ((int)blockAlign + 15) * 2; ++index) { MSADPCMToPCM.getNibbleBlock(Source.ReadByte(), nibbleBlock); binaryWriter.Write(MSADPCMToPCM.calculateSample(nibbleBlock[0], predictor1, ref sample_1_1, ref sample_2_1, ref delta1)); binaryWriter.Write(MSADPCMToPCM.calculateSample(nibbleBlock[1], predictor2, ref sample_1_2, ref sample_2_2, ref delta2)); } } } else { Console.WriteLine("MSADPCM WAVEDATA IS NOT MONO OR STEREO!"); binaryWriter.Close(); memoryStream.Close(); return((byte[])null); } binaryWriter.Close(); memoryStream.Close(); return(memoryStream.ToArray()); }