示例#1
0
        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);
            }
        }
示例#2
0
        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
                        );
                }
            }
        }
示例#3
0
        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;
        }
示例#4
0
        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
                    );
            }
        }
示例#5
0
        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;
        }
示例#6
0
        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());
        }