Ejemplo n.º 1
0
        public static unsafe int LoadALBufferFromMem(uint bufNumber, byte* samplePointer, uint sampleSize,
            uint uncompSampleSize = 0)
        {
            var wavMem = new MemBufferFileIo(samplePointer, sampleSize);
            var tmp = wavMem.ToSfVirtualIo();
            var sfInfo = new LibsndfileInfo();
            var sample = sndFileApi.OpenVirtual(ref tmp, LibsndfileMode.Read, ref sfInfo, &wavMem);

            if(sample == IntPtr.Zero)
            {
                Sys.DebugLog(LOG_FILENAME, "Error: can't load sample #{0:D3} from sample block!", bufNumber);
                Sys.DebugLog(LOG_FILENAME, $"Libsndfile error: {sndFileApi.Error(IntPtr.Zero):G} ({sndFileApi.ErrorString(IntPtr.Zero)})");
                return -1;
            }

            // Uncomp_sample_size explicitly specifies amount of raw sample data
            // to load into buffer. It is only used in TR4/5 with ADPCM samples,
            // because full-sized ADPCM sample contains a bit of silence at the end,
            // which should be removed. That's where uncomp_sample_size comes into
            // business.
            // Note that we also need to compare if uncomp_sample_size is smaller
            // than native wav length, because for some reason many TR5 uncomp sizes
            // are messed up and actually more than actual sample size.

            var realSize = sfInfo.Frames * sizeof(ushort);

            if (uncompSampleSize == 0 || realSize < uncompSampleSize)
            {
                uncompSampleSize = (uint)realSize;
            }

            // We need to change buffer size, as we're using floats here.

            if (AUDIO_OPENAL_FLOAT)
                uncompSampleSize = (uncompSampleSize / sizeof(ushort)) * sizeof(float);
            else
                uncompSampleSize = uncompSampleSize / sizeof(ushort) * sizeof(short);

            // Find out sample format and load it correspondingly.
            // Note that with OpenAL, we can have samples of different formats in same level.

            var result = FillALBuffer(bufNumber, sample, uncompSampleSize, sfInfo);

            sndFileApi.Close(sample);

            return result ? 0 : -3; // Zero means success
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Wad loading
        /// </summary>
        private unsafe bool loadWad(byte index, string filename)
        {
            if (index >= TR_AUDIO_STREAM_WAD_COUNT)
            {
                ConsoleInfo.Instance.Warning(Strings.SYSWARN_WAD_OUT_OF_BOUNDS, TR_AUDIO_STREAM_WAD_COUNT);
                return false;
            }
            FileStream wadFile;
            try
            {
                wadFile = File.OpenRead(filename);
            }
            catch
            {
                ConsoleInfo.Instance.Warning(Strings.SYSWARN_FILE_NOT_FOUND, filename);
                return false;
            }

            var trackName = "";
            uint offset = 0;
            uint length = 0;

            using (var br = Helper.CreateInstance<BinaryReader>(wadFile, Encoding.UTF8, true))
            {
                br.BaseStream.Position = index * TR_AUDIO_STREAM_WAD_STRIDE;
                trackName = br.ParseString(TR_AUDIO_STREAM_WAD_NAMELENGTH, true);
                length = br.ReadUInt32();
                offset = br.ReadUInt32();
                br.BaseStream.Position = offset;
            }

            if ((IntPtr) wadBuf != IntPtr.Zero)
            {
                Marshal.FreeHGlobal((IntPtr) wadBuf);
            }

            if ((IntPtr)wadMemIo != IntPtr.Zero)
            {
                Marshal.FreeHGlobal((IntPtr)wadMemIo);
            }
            
            wadBuf = (byte*)Marshal.AllocHGlobal((int) length);
            var buf = new byte[(int)length];
            wadFile.Read(buf, 0, (int) length);
            Marshal.Copy(buf, 0, (IntPtr)wadBuf, (int)length);
            wadMemIo = (MemBufferFileIo*) Marshal.AllocHGlobal(sizeof (MemBufferFileIo));
            var s = new MemBufferFileIo(wadBuf, (int) length);
            Marshal.StructureToPtr(s, (IntPtr)wadMemIo, false);
            var vio = wadMemIo->ToSfVirtualIo();
            if ((sndFile = sndFileApi.OpenVirtual(ref vio, LibsndfileMode.Read, ref sfInfo, wadMemIo)) == IntPtr.Zero)
            {
                ConsoleInfo.Instance.Warning(Strings.SYSWARN_WAD_SEEK_FAILED, offset);
                ConsoleInfo.Instance.AddLine(
                    $"Libsndfile error: {sndFileApi.Error(IntPtr.Zero):G} ({sndFileApi.ErrorString(IntPtr.Zero)})",
                    FontStyle.ConsoleWarning);
                method = TR_AUDIO_STREAM_METHOD.Unknown;
                return false;
            }

            ConsoleInfo.Instance.Notify(Strings.SYSNOTE_WAD_PLAYING, filename, offset, length);
            ConsoleInfo.Instance.Notify(Strings.SYSNOTE_TRACK_OPENED, trackName, sfInfo.Channels, sfInfo.SampleRate);

            if (AUDIO_OPENAL_FLOAT)
                format = sfInfo.Channels == 1 ? ALFormat.MonoFloat32Ext : ALFormat.StereoFloat32Ext;
            else
                format = sfInfo.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16;

            rate = sfInfo.SampleRate;

            return true; // Success!
        }