Example #1
0
 public WadSoundInfo(WadSoundInfo s)
 {
     Id              = s.Id;
     Name            = s.Name;
     Volume          = s.Volume;
     RangeInSectors  = s.RangeInSectors;
     Chance          = s.Chance;
     PitchFactor     = s.PitchFactor;
     DisablePanning  = s.DisablePanning;
     RandomizePitch  = s.RandomizePitch;
     RandomizeVolume = s.RandomizeVolume;
     LoopBehaviour   = s.LoopBehaviour;
     Samples         = new List <WadSample>();
     SoundCatalog    = s.SoundCatalog;
     Global          = s.Global;
     Indexed         = s.Indexed;
     foreach (var sample in s.Samples)
     {
         Samples.Add(new WadSample(sample.FileName));
     }
 }
Example #2
0
        private static WadSounds ReadFromTxt(string filename)
        {
            var sounds = new WadSounds();

            try
            {
                using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    using (var reader = new StreamReader(fileStream))
                    {
                        ushort soundId = 0;
                        while (!reader.EndOfStream)
                        {
                            var s     = reader.ReadLine().Trim();
                            var sound = new WadSoundInfo(soundId);

                            // Get the name (ends with :)
                            int endOfSoundName = s.IndexOf(':');
                            if (endOfSoundName == -1)
                            {
                                soundId++;
                                continue;
                            }

                            sound.Name         = s.Substring(0, endOfSoundName);
                            sound.SoundCatalog = filename;

                            // Get everything else and remove empty tokens
                            var tokens = s.Substring(endOfSoundName + 1).Split(' ', '\t').Where(token => !string.IsNullOrEmpty(token)).ToList();
                            if (tokens.Count <= 1)
                            {
                                soundId++;
                                continue;
                            }

                            // Trim comments
                            int commentTokenIndex = tokens.FindIndex(t => t.StartsWith(";"));
                            if (commentTokenIndex != -1)
                            {
                                tokens.RemoveRange(commentTokenIndex, tokens.Count - commentTokenIndex);
                            }

                            var anyTokenFound = false;
                            for (int i = 0; i < tokens.Count; i++)
                            {
                                var   token = tokens[i];
                                short temp  = 0;

                                if (token.StartsWith("PIT", StringComparison.InvariantCultureIgnoreCase) && short.TryParse(token.Substring(3), out temp))
                                {
                                    sound.PitchFactor = temp;
                                    anyTokenFound     = true;
                                }
                                else if (token.StartsWith("RAD", StringComparison.InvariantCultureIgnoreCase) && short.TryParse(token.Substring(3), out temp))
                                {
                                    sound.RangeInSectors = temp;
                                    anyTokenFound        = true;
                                }
                                else if (token.StartsWith("VOL", StringComparison.InvariantCultureIgnoreCase) && short.TryParse(token.Substring(3), out temp))
                                {
                                    sound.Volume  = temp;
                                    anyTokenFound = true;
                                }
                                else if (token.StartsWith("CH", StringComparison.InvariantCultureIgnoreCase) && short.TryParse(token.Substring(2), out temp))
                                {
                                    sound.Chance  = temp;
                                    anyTokenFound = true;
                                }
                                else if (token.Equals("P", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.RandomizePitch = true;
                                    anyTokenFound        = true;
                                }
                                else if (token.Equals("V", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.RandomizeVolume = true;
                                    anyTokenFound         = true;
                                }
                                else if (token.Equals("N", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.DisablePanning = true;
                                    anyTokenFound        = true;
                                }
                                else if (token.Equals("L", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.LoopBehaviour = WadSoundLoopBehaviour.Looped;
                                    anyTokenFound       = true;
                                }
                                else if (token.Equals("R", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.LoopBehaviour = WadSoundLoopBehaviour.OneShotRewound;
                                    anyTokenFound       = true;
                                }
                                else if (token.Equals("W", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    sound.LoopBehaviour = WadSoundLoopBehaviour.OneShotWait;
                                    anyTokenFound       = true;
                                }
                                else if (token.StartsWith("#g"))
                                {
                                    sound.Global  = true;
                                    anyTokenFound = true;
                                }
                                else if (!token.StartsWith("#") && !anyTokenFound)
                                {
                                    sound.Samples.Add(new WadSample(token + ".wav"));
                                }

                                if (token.StartsWith("#"))
                                {
                                    sound.Indexed = true;
                                }
                            }

                            sounds.SoundInfos.Add(sound);
                            soundId++;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return(null);
            }

            return(sounds);
        }
Example #3
0
        private static WadSounds ReadFromSfx(string filename)
        {
            var samples = new List <string>();

            // Read version
            int version = 129;

            using (var readerVersion = new BinaryReaderEx(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)))
                version = readerVersion.ReadInt32();

            // Read samples
            var samPath = Path.GetDirectoryName(filename) + "\\" + Path.GetFileNameWithoutExtension(filename) + ".sam";

            using (var readerSounds = new StreamReader(new FileStream(samPath, FileMode.Open, FileAccess.Read, FileShare.Read)))
                while (!readerSounds.EndOfStream)
                {
                    samples.Add(readerSounds.ReadLine());
                }

            // Read sounds
            int soundMapSize = 0;

            short[] soundMap;
            var     wadSoundInfos = new List <wad_sound_info>();
            var     soundInfos    = new List <WadSoundInfo>();

            var sfxPath = Path.GetDirectoryName(filename) + "\\" + Path.GetFileNameWithoutExtension(filename) + ".sfx";

            using (var readerSfx = new BinaryReaderEx(new FileStream(sfxPath, FileMode.Open, FileAccess.Read, FileShare.Read)))
            {
                // Try to guess the WAD version
                readerSfx.BaseStream.Seek(740, SeekOrigin.Begin);
                short first  = readerSfx.ReadInt16();
                short second = readerSfx.ReadInt16();
                version = ((first == -1 || second == (first + 1)) ? 130 : 129);
                readerSfx.BaseStream.Seek(0, SeekOrigin.Begin);

                soundMapSize = (version == 130 ? 2048 : 370);
                soundMap     = new short[soundMapSize];
                for (var i = 0; i < soundMapSize; i++)
                {
                    soundMap[i] = readerSfx.ReadInt16();
                }

                var numSounds = readerSfx.ReadUInt32();

                for (var i = 0; i < numSounds; i++)
                {
                    var info = new wad_sound_info();
                    info.Sample          = readerSfx.ReadUInt16();
                    info.Volume          = readerSfx.ReadByte();
                    info.Range           = readerSfx.ReadByte();
                    info.Chance          = readerSfx.ReadByte();
                    info.Pitch           = readerSfx.ReadByte();
                    info.Characteristics = readerSfx.ReadUInt16();
                    wadSoundInfos.Add(info);
                }
            }

            // Convert old data to new format
            for (int i = 0; i < soundMapSize; i++)
            {
                // Check if sound is defined at all
                if (soundMap[i] == -1 || soundMap[i] >= wadSoundInfos.Count)
                {
                    continue;
                }

                // Fill the new sound info
                var oldInfo = wadSoundInfos[soundMap[i]];
                var newInfo = new WadSoundInfo(i);
                newInfo.Name           = TrCatalog.GetOriginalSoundName(TRVersion.Game.TR4, (uint)i);
                newInfo.Volume         = (int)Math.Round(oldInfo.Volume * 100.0f / 255.0f);
                newInfo.RangeInSectors = oldInfo.Range;
                newInfo.Chance         = (int)Math.Round(oldInfo.Chance * 100.0f / 255.0f);
                if (newInfo.Chance == 0)
                {
                    newInfo.Chance = 100;                      // Convert legacy chance value
                }
                newInfo.PitchFactor     = (int)Math.Round((oldInfo.Pitch > 127 ? oldInfo.Pitch - 256 : oldInfo.Pitch) * 100.0f / 128.0f);
                newInfo.RandomizePitch  = ((oldInfo.Characteristics & 0x2000) != 0);
                newInfo.RandomizeVolume = ((oldInfo.Characteristics & 0x4000) != 0);
                newInfo.DisablePanning  = ((oldInfo.Characteristics & 0x1000) != 0);
                newInfo.LoopBehaviour   = (WadSoundLoopBehaviour)(oldInfo.Characteristics & 0x03);
                newInfo.SoundCatalog    = sfxPath;

                // Read all samples linked to this sound info (for example footstep has 4 samples)
                int numSamplesInGroup = (oldInfo.Characteristics & 0x00fc) >> 2;
                for (int j = oldInfo.Sample; j < oldInfo.Sample + numSamplesInGroup; j++)
                {
                    newInfo.Samples.Add(new WadSample(samples[j]));
                }
                soundInfos.Add(newInfo);
            }

            var sounds = new WadSounds(soundInfos);

            return(sounds);
        }
Example #4
0
        public static void PlaySoundInfo(Level level, WadSoundInfo soundInfo)
        {
            if (soundInfo == null || soundInfo.Samples == null || soundInfo.Samples.Count == 0)
            {
                return;
            }

            int channelIndex = FindPlayingIndex(soundInfo.Id);

            if (channelIndex >= 0)
            {
                switch (soundInfo.LoopBehaviour)
                {
                case WadSoundLoopBehaviour.Looped:
                case WadSoundLoopBehaviour.OneShotWait:
                    return;

                case WadSoundLoopBehaviour.OneShotRewound:
                    StopSample(channelIndex);
                    break;

                case WadSoundLoopBehaviour.None:
                    channelIndex = GetFreeChannel();
                    break;
                }
            }
            else
            {
                channelIndex = GetFreeChannel();
            }

            _indices[channelIndex] = soundInfo.Id;

            // Figure out the precise play parameters
            int   sampleIndex;
            int   loopCount = soundInfo.LoopBehaviour == WadSoundLoopBehaviour.Looped ? 3 : 1;
            float pan       = 0.0f;
            float volume    = soundInfo.Volume / 100.0f;
            float pitch     = (soundInfo.PitchFactor / 127.0f) + 1.0f;
            float chance    = soundInfo.Chance == 0 ? 1.0f : soundInfo.Chance / 100.0f;

            lock (_rng)
            {
                if (chance != 1.0f && _rng.NextDouble() > chance)
                {
                    return;
                }

                sampleIndex = _rng.Next(0, soundInfo.Samples.Count);
                if (sampleIndex == soundInfo.Samples.Count)
                {
                    sampleIndex = soundInfo.Samples.Count - 1;
                }

                if (!soundInfo.DisablePanning)
                {
                    pan = (float)((_rng.NextDouble() - 0.5f) * 1.6);
                }
                if (soundInfo.RandomizePitch)
                {
                    pitch += (float)(_rng.NextDouble() * (6000.0 / 65536.0));
                }
                if (soundInfo.RandomizeVolume)
                {
                    volume -= (float)_rng.NextDouble() * 0.125f;
                }
            }

            PlaySample(level, soundInfo.Samples[sampleIndex], channelIndex, volume, pitch, pan, loopCount);
        }
Example #5
0
        private static bool LoadSoundInfo(ChunkReader chunkIO, Wad2 wad, Dictionary <long, WadSample> samples,
                                          out WadSoundInfo soundInfo, out long index)
        {
            var   tempSoundInfo = new WadSoundInfo(0);
            long  tempIndex     = 0;
            float volume        = 0;
            float chance        = 0;
            float pitch         = 0;
            float range         = 0;

            chunkIO.ReadChunks((id2, chunkSize2) =>
            {
                // XML_SOUND_SYSTEM
                if (id2 == Wad2Chunks.SoundInfoIndex)
                {
                    tempIndex = chunkIO.ReadChunkLong(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoVolume)
                {
                    volume = chunkIO.ReadChunkFloat(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoRange)
                {
                    range = chunkIO.ReadChunkFloat(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoPitch)
                {
                    pitch = chunkIO.ReadChunkFloat(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoChance)
                {
                    chance = chunkIO.ReadChunkFloat(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoDisablePanning)
                {
                    tempSoundInfo.DisablePanning = chunkIO.ReadChunkBool(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoRandomizePitch)
                {
                    tempSoundInfo.RandomizePitch = chunkIO.ReadChunkBool(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoRandomizeVolume)
                {
                    tempSoundInfo.RandomizeVolume = chunkIO.ReadChunkBool(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoLoopBehaviour)
                {
                    tempSoundInfo.LoopBehaviour = (WadSoundLoopBehaviour)(3 & chunkIO.ReadChunkByte(chunkSize2));
                }
                else if (id2 == Wad2Chunks.SoundInfoName || id2 == Wad2Chunks.SoundInfoNameObsolete)
                {
                    tempSoundInfo.Name = chunkIO.ReadChunkString(chunkSize2);
                }
                else if (id2 == Wad2Chunks.SoundInfoSampleIndex)
                {
                    tempSoundInfo.Samples.Add(samples[chunkIO.ReadChunkInt(chunkSize2)]); // Legacy
                }
                else
                {
                    return(false);
                }
                return(true);
            });

            // Convert from floats to ints
            tempSoundInfo.Volume         = (int)Math.Round(volume * 100.0f);
            tempSoundInfo.RangeInSectors = (int)range;
            tempSoundInfo.Chance         = (int)Math.Round(chance * 100.0f);
            tempSoundInfo.PitchFactor    = (int)Math.Round((pitch - 1.0f) * 100.0f);

            // Try to get the old ID
            tempSoundInfo.Id = TrCatalog.TryGetSoundInfoIdByDescription(wad.GameVersion, tempSoundInfo.Name);

            if (string.IsNullOrWhiteSpace(tempSoundInfo.Name))
            {
                tempSoundInfo.Name = TrCatalog.GetOriginalSoundName(wad.GameVersion, unchecked ((uint)tempIndex));
            }

            index     = tempIndex;
            soundInfo = tempSoundInfo;

            return(true);
        }