Пример #1
0
        void ReadHeader(EriFile erif)
        {
            var section = erif.ReadSection();

            if (section.Id != "Header  " || section.Length <= 0 || section.Length > int.MaxValue)
            {
                return(null);
            }
            m_stream_pos = erif.BaseStream.Position + section.Length;
            section      = erif.ReadSection();
            if (section.Id != "FileHdr" || section.Length < 8)
            {
                return(null);
            }
            var file_hdr = new byte[section.Length];

            erif.Read(file_hdr, 0, file_hdr.Length);
            if (0 == (file_hdr[5] & 1))
            {
                return(null);
            }
            section = erif.ReadSection();
            if (section.Id != "SoundInf" || section.Length < 0x24)
            {
                return(null);
            }

            var info = new EmsacSoundInfo();

            info.Version        = erif.ReadInt32();
            info.Transformation = (CvType)erif.ReadInt32();
            info.Architecture   = (EriCode)erif.ReadInt32();
            info.ChannelCount   = erif.ReadInt32();
            info.SamplesPerSec  = erif.ReadUInt32();
            info.BlocksetCount  = erif.ReadUInt32();
            info.SubbandDegree  = erif.ReadInt32();
            info.AllSampleCount = erif.ReadInt32();
            info.LappedDegree   = erif.ReadInt32();
            SetSoundInfo(info);
            SetWaveFormat(info);

            erif.BaseStream.Position = m_stream_pos;
            var stream_size = erif.FindSection("Stream  ");

            m_stream_pos = erif.BaseStream.Position;
        }
Пример #2
0
        private Stream LoadChunks(EriFile erif)
        {
            uint            current_sample = 0;
            List <MioChunk> chunks         = new List <MioChunk>();

            try
            {
                erif.BaseStream.Position = m_stream_pos;
                for (;;)
                {
                    long chunk_length = erif.FindSection("SoundStm");
                    if (chunk_length > int.MaxValue)
                    {
                        throw new FileSizeException();
                    }
                    var chunk = new MioChunk();
                    chunk.FirstSample = current_sample;
                    chunk.Version     = erif.ReadByte();
                    chunk.Flags       = erif.ReadByte();
                    erif.ReadInt16();
                    chunk.SampleCount = erif.ReadUInt32();
                    chunk.Position    = erif.BaseStream.Position;
                    chunk.Size        = (uint)(chunk_length - 8);
                    current_sample   += chunk.SampleCount;
                    chunks.Add(chunk);
                    erif.BaseStream.Seek(chunk.Size, SeekOrigin.Current);
                }
            }
            catch (EndOfStreamException) { /* ignore EOF errors */ }
            m_total_samples = current_sample;
            if (0 == m_total_samples)
            {
                m_decode_finished = true;
                return(Stream.Null);
            }
            uint sample_bytes = (uint)ChannelCount * BitsPerSample / 8;
            var  total_bytes  = m_total_samples * sample_bytes;

            m_wait_handles = new WaitHandle[2] {
                m_available_chunk, m_decode_complete
            };
            m_chunk_queue = new ConcurrentQueue <byte[]>();
            m_worker      = new BackgroundWorker();
            m_worker.WorkerSupportsCancellation = true;
            m_worker.DoWork += DoWork_Decode;
            m_worker.RunWorkerAsync(chunks);
            return(new MemoryStream((int)total_bytes));
        }
Пример #3
0
        public MioInput(Stream file) : base(file)
        {
            file.Position = 0x40;
            using (var erif = new EriFile(file))
            {
                var section = erif.ReadSection();
                if (section.Id != "Header  " || section.Length <= 0 || section.Length > int.MaxValue)
                {
                    throw new InvalidFormatException();
                }
                m_stream_pos = 0x50 + section.Length;
                int header_size = (int)section.Length;
                while (header_size > 0x10)
                {
                    section      = erif.ReadSection();
                    header_size -= 0x10;
                    if (section.Length <= 0 || section.Length > header_size)
                    {
                        break;
                    }
                    if ("SoundInf" == section.Id)
                    {
                        m_info                = new MioInfoHeader();
                        m_info.Version        = erif.ReadInt32();
                        m_info.Transformation = (CvType)erif.ReadInt32();
                        m_info.Architecture   = (EriCode)erif.ReadInt32();
                        m_info.ChannelCount   = erif.ReadInt32();
                        m_info.SamplesPerSec  = erif.ReadUInt32();
                        m_info.BlocksetCount  = erif.ReadUInt32();
                        m_info.SubbandDegree  = erif.ReadInt32();
                        m_info.AllSampleCount = erif.ReadUInt32();
                        m_info.LappedDegree   = erif.ReadUInt32();
                        m_info.BitsPerSample  = erif.ReadUInt32();
                        break;
                    }
                    header_size -= (int)section.Length;
                    erif.BaseStream.Seek(section.Length, SeekOrigin.Current);
                }
                if (null == m_info)
                {
                    throw new InvalidFormatException("MIO sound header not found");
                }

                erif.BaseStream.Position = m_stream_pos;
                var stream_size = erif.FindSection("Stream  ");
                m_stream_pos = erif.BaseStream.Position;

                m_pmiod = new MioDecoder(m_info);
                if (EriCode.Nemesis != m_info.Architecture)
                {
                    m_pmioc = new HuffmanDecodeContext(0x10000);
                }
                else
                {
                    throw new NotImplementedException("MIO Nemesis encoding not implemented");
                }

                int pcm_bitrate = (int)(m_info.SamplesPerSec * BitsPerSample * ChannelCount);
                var format      = new GameRes.WaveFormat();
                format.FormatTag             = 1;
                format.Channels              = (ushort)ChannelCount;
                format.SamplesPerSecond      = m_info.SamplesPerSec;
                format.BitsPerSample         = (ushort)BitsPerSample;
                format.BlockAlign            = (ushort)(BitsPerSample / 8 * format.Channels);
                format.AverageBytesPerSecond = (uint)pcm_bitrate / 8;
                this.Format      = format;
                m_decoded_stream = LoadChunks(erif);

                if (0 != m_total_samples)
                {
                    m_bitrate = (int)(stream_size * 8 * m_info.SamplesPerSec / m_total_samples);
                }
                this.PcmSize = m_total_samples * ChannelCount * BitsPerSample / 8;
                m_decoded_stream.Position = 0;
            }
        }