FromStream() 공개 정적인 메소드

Creates a SoundEffect object based on the specified data stream.
The Stream object must point to the head of a valid PCM wave file. Also, this wave file must be in the RIFF bitstream format.
public static FromStream ( Stream s ) : SoundEffect
s Stream Stream object containing PCM wave data.
리턴 SoundEffect
예제 #1
0
        private XnaSoundEffect FromContent(string assetname)
        {
            assetName = Game.FileExtensionCheck(assetName, soundExtensions);
            FileStream     fs    = new FileStream(assetName, FileMode.Open);
            XnaSoundEffect sound = XnaSoundEffect.FromStream(fs);

            fs.Close();
            return(sound);
        }
예제 #2
0
        /// <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)
        {
            //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;

            nonStreamingWaveBankFilename = FileHelpers.NormalizeFilePathSeparators(nonStreamingWaveBankFilename);

#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 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

                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
                    // TODO: Wouldn't storing a SoundEffectInstance like this
                    // result in the "parent" SoundEffect being garbage collected?

                    SharpDX.Multimedia.WaveFormat waveFormat = new SharpDX.Multimedia.WaveFormat(rate, chans);
                    var sfx = new SoundEffect(audiodata, 0, audiodata.Length, rate, (AudioChannels)chans, wavebankentry.LoopRegion.Offset, wavebankentry.LoopRegion.Length)
                    {
                        _format = waveFormat
                    };

                    _sounds[current_entry] = sfx;
#else
                    _sounds[current_entry] = new SoundEffect(audiodata, rate, (AudioChannels)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);
                            audioFile.Seek(0, SeekOrigin.Begin);

                            _sounds[current_entry] = SoundEffect.FromStream(audioFile);
                        }
#else
                        throw new NotImplementedException();
#endif
                    }
                    else
                    {
                        //An xWMA or XMA2 file. Can't be played atm :(
                        throw new NotImplementedException();
                    }
                }
                else if (codec == MiniFormatTag_ADPCM)
                {
#if DIRECTX
                    _sounds[current_entry] = new SoundEffect(audiodata, rate, (AudioChannels)chans)
                    {
                        _format = new SharpDX.Multimedia.WaveFormatAdpcm(rate, chans, align)
                    };
#else
                    using (var dataStream = new MemoryStream(audiodata)) {
                        using (var source = new BinaryReader(dataStream)) {
                            _sounds[current_entry] = new SoundEffect(
                                MSADPCMToPCM.MSADPCM_TO_PCM(source, (short)chans, (short)align),
                                rate,
                                (AudioChannels)chans
                                );
                        }
                    }
#endif
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            audioEngine.Wavebanks[_bankName] = this;
        }