Beispiel #1
0
        /// <summary />
        public SoundService()
        {
            Service = this;

            _ambientReverb  = ReverbType.NoReverb;
            _distanceFactor = 1.0f;
            _dopplerScale   = 1.0f;
            _rolloffScale   = 1.0f;
        }
Beispiel #2
0
        public void Init(byte reverbAmt)
        {
            DSMasterVolume = ROM.Instance.Game.Engine.Volume / (float)0xF;
            numTracks      = ROM.Instance.Game.Engine.TrackLimit + 1; // 1 for program use

            trackBuffers = new float[numTracks][];
            reverbs      = new Reverb[numTracks];

            int amt = SamplesPerBuffer * 2;

            for (int i = 0; i < numTracks; i++)
            {
                trackBuffers[i] = new float[amt];
            }

            ReverbType reverbType = ROM.Instance.Game.Engine.ReverbType;

            reverbType = ReverbType.None; // For now because of crashes

            byte engineReverb = ROM.Instance.Game.Engine.Reverb;
            byte reverb       = (byte)(engineReverb >= 0x80 ? engineReverb & 0x7F : reverbAmt & 0x7F);

            for (int i = 0; i < numTracks; i++)
            {
                byte numBuffers = (byte)(0x630 / (ROM.Instance.Game.Engine.Frequency / Engine.AGB_FPS));
                switch (reverbType)
                {
                default: reverbs[i] = new Reverb(reverb, numBuffers); break;

                case ReverbType.Camelot1: reverbs[i] = new ReverbCamelot1(reverb, numBuffers); break;

                case ReverbType.Camelot2: reverbs[i] = new ReverbCamelot2(reverb, numBuffers, 53 / 128f, -8 / 128f); break;

                case ReverbType.MGAT: reverbs[i] = new ReverbCamelot2(reverb, numBuffers, 32 / 128f, -6 / 128f); break;

                case ReverbType.None: reverbs[i] = null; break;
                }
            }
        }
Beispiel #3
0
        public Config(byte[] rom)
        {
            const string configFile = "MP2K.yaml";

            using (StreamReader fileStream = File.OpenText(Util.Utils.CombineWithBaseDirectory(configFile)))
            {
                string gcv = string.Empty;
                try
                {
                    ROM      = rom;
                    Reader   = new EndianBinaryReader(new MemoryStream(rom));
                    GameCode = Reader.ReadString(4, 0xAC);
                    Version  = Reader.ReadByte(0xBC);
                    gcv      = $"{GameCode}_{Version:X2}";
                    var yaml = new YamlStream();
                    yaml.Load(fileStream);

                    var             mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
                    YamlMappingNode game;
                    try
                    {
                        game = (YamlMappingNode)mapping.Children.GetValue(gcv);
                    }
                    catch (BetterKeyNotFoundException)
                    {
                        throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KMissingGameCode, gcv)));
                    }

                    YamlNode nameNode               = null,
                             songTableOffsetsNode   = null,
                             songTableSizesNode     = null,
                             sampleRateNode         = null,
                             reverbTypeNode         = null,
                             reverbNode             = null,
                             volumeNode             = null,
                             hasGoldenSunSynthsNode = null,
                             hasPokemonCompression  = null;
                    void Load(YamlMappingNode gameToLoad)
                    {
                        if (gameToLoad.Children.TryGetValue("Copy", out YamlNode node))
                        {
                            YamlMappingNode copyGame;
                            try
                            {
                                copyGame = (YamlMappingNode)mapping.Children.GetValue(node);
                            }
                            catch (BetterKeyNotFoundException ex)
                            {
                                throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KCopyInvalidGameCode, ex.Key)));
                            }
                            Load(copyGame);
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Name), out node))
                        {
                            nameNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SongTableOffsets), out node))
                        {
                            songTableOffsetsNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SongTableSizes), out node))
                        {
                            songTableSizesNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(SampleRate), out node))
                        {
                            sampleRateNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(ReverbType), out node))
                        {
                            reverbTypeNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Reverb), out node))
                        {
                            reverbNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Volume), out node))
                        {
                            volumeNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(HasGoldenSunSynths), out node))
                        {
                            hasGoldenSunSynthsNode = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(HasPokemonCompression), out node))
                        {
                            hasPokemonCompression = node;
                        }
                        if (gameToLoad.Children.TryGetValue(nameof(Playlists), out node))
                        {
                            var playlists = (YamlMappingNode)node;
                            foreach (KeyValuePair <YamlNode, YamlNode> kvp in playlists)
                            {
                                string name  = kvp.Key.ToString();
                                var    songs = new List <Song>();
                                foreach (KeyValuePair <YamlNode, YamlNode> song in (YamlMappingNode)kvp.Value)
                                {
                                    long songIndex = Util.Utils.ParseValue(string.Format(Strings.ConfigKeySubkey, nameof(Playlists)), song.Key.ToString(), 0, long.MaxValue);
                                    if (songs.Any(s => s.Index == songIndex))
                                    {
                                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KSongRepeated, name, songIndex)));
                                    }
                                    songs.Add(new Song(songIndex, song.Value.ToString()));
                                }
                                Playlists.Add(new Playlist(name, songs));
                            }
                        }
                    }

                    Load(game);

                    if (nameNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Name), null);
                    }
                    Name = nameNode.ToString();
                    if (songTableOffsetsNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SongTableOffsets), null);
                    }
                    string[] songTables    = songTableOffsetsNode.ToString().SplitSpace(StringSplitOptions.RemoveEmptyEntries);
                    int      numSongTables = songTables.Length;
                    if (numSongTables == 0)
                    {
                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyNoEntries, nameof(SongTableOffsets))));
                    }
                    if (songTableSizesNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SongTableSizes), null);
                    }
                    string[] sizes = songTableSizesNode.ToString().SplitSpace(StringSplitOptions.RemoveEmptyEntries);
                    if (sizes.Length != numSongTables)
                    {
                        throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorAlphaDreamMP2KSongTableCounts, nameof(SongTableSizes), nameof(SongTableOffsets))));
                    }
                    SongTableOffsets = new int[numSongTables];
                    SongTableSizes   = new long[numSongTables];
                    int maxOffset = rom.Length - 1;
                    for (int i = 0; i < numSongTables; i++)
                    {
                        SongTableSizes[i]   = Util.Utils.ParseValue(nameof(SongTableSizes), sizes[i], 1, maxOffset);
                        SongTableOffsets[i] = (int)Util.Utils.ParseValue(nameof(SongTableOffsets), songTables[i], 0, maxOffset);
                    }
                    if (sampleRateNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(SampleRate), null);
                    }
                    SampleRate = (int)Util.Utils.ParseValue(nameof(SampleRate), sampleRateNode.ToString(), 0, Utils.FrequencyTable.Length - 1);
                    if (reverbTypeNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(ReverbType), null);
                    }
                    ReverbType = Util.Utils.ParseEnum <ReverbType>(nameof(ReverbType), reverbTypeNode.ToString());
                    if (reverbNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Reverb), null);
                    }
                    Reverb = (byte)Util.Utils.ParseValue(nameof(Reverb), reverbNode.ToString(), byte.MinValue, byte.MaxValue);
                    if (volumeNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(Volume), null);
                    }
                    Volume = (byte)Util.Utils.ParseValue(nameof(Volume), volumeNode.ToString(), 0, 15);
                    if (hasGoldenSunSynthsNode == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(HasGoldenSunSynths), null);
                    }
                    HasGoldenSunSynths = Util.Utils.ParseBoolean(nameof(HasGoldenSunSynths), hasGoldenSunSynthsNode.ToString());
                    if (hasPokemonCompression == null)
                    {
                        throw new BetterKeyNotFoundException(nameof(HasPokemonCompression), null);
                    }
                    HasPokemonCompression = Util.Utils.ParseBoolean(nameof(HasPokemonCompression), hasPokemonCompression.ToString());

                    // The complete playlist
                    if (!Playlists.Any(p => p.Name == "Music"))
                    {
                        Playlists.Insert(0, new Playlist(Strings.PlaylistMusic, Playlists.SelectMany(p => p.Songs).Distinct().OrderBy(s => s.Index)));
                    }
                }
                catch (BetterKeyNotFoundException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyMissing, ex.Key)));
                }
                catch (InvalidValueException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorAlphaDreamMP2KParseGameCode, gcv, configFile, Environment.NewLine + ex.Message));
                }
                catch (YamlDotNet.Core.YamlException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + ex.Message));
                }
            }
        }
Beispiel #4
0
 public AnEngine(EngineType type, ReverbType reverbType, byte reverb, byte volume, byte trackLimit, int frequency, bool hasGoldenSunSynths)
 {
     Type = type; ReverbType = reverbType; Reverb = reverb; Volume = volume; TrackLimit = trackLimit; Frequency = frequency; HasGoldenSunSynths = hasGoldenSunSynths;
 }
Beispiel #5
0
        void LoadGames()
        {
            var yaml = new YamlStream();

            yaml.Load(new StringReader(File.ReadAllText("Games.yaml")));

            var mapping = (YamlMappingNode)yaml.Documents[0].RootNode;

            Games = new Dictionary <string, AGame>();
            foreach (var g in mapping)
            {
                string           code, name, creator;
                EngineType       engineType = EngineType.M4A; ReverbType reverbType = ReverbType.Normal;
                byte             engineReverb = 0, engineVolume = 0xF, engineTrackLimit = 0x10;
                int              engineFrequency = 13379; bool engineHasGoldenSunSynths = false;
                int[]            tables, tableSizes;
                List <APlaylist> playlists;
                string           remap = string.Empty;
                int              voiceTable = 0, sampleTable = 0, sampleTableSize = 0;

                code = g.Key.ToString();
                var game = (YamlMappingNode)g.Value;

                // Basic info
                name = game.Children["Name"].ToString();

                // SongTables
                var songTables = game.Children["SongTable"].ToString().Split(' ');
                tables = new int[songTables.Length]; tableSizes = new int[songTables.Length];
                for (int i = 0; i < songTables.Length; i++)
                {
                    tables[i] = (int)Utils.ParseValue(songTables[i]);
                }

                // MLSS info
                if (game.Children.TryGetValue("VoiceTable", out YamlNode vTable))
                {
                    voiceTable = (int)Utils.ParseValue(vTable.ToString());
                }
                if (game.Children.TryGetValue("SampleTable", out YamlNode sTable))
                {
                    sampleTable = (int)Utils.ParseValue(sTable.ToString());
                }
                if (game.Children.TryGetValue("SampleTableSize", out YamlNode saTableSize))
                {
                    sampleTableSize = (int)Utils.ParseValue(saTableSize.ToString());
                }

                // If we are to copy another game's config
                if (game.Children.TryGetValue("Copy", out YamlNode copy))
                {
                    game = (YamlMappingNode)mapping.Children[copy];
                }

                // SongTable Sizes
                string[] sizes = { };
                if (game.Children.TryGetValue("SongTableSize", out YamlNode soTableSize))
                {
                    sizes = soTableSize.ToString().Split(' ');
                }
                for (int i = 0; i < songTables.Length; i++)
                {
                    tableSizes[i] = DefaultTableSize;
                    if (i < sizes.Length)
                    {
                        tableSizes[i] = (int)Utils.ParseValue(sizes[i]);
                    }
                }

                // Creator name (required)
                creator = game.Children["Creator"].ToString();

                // Remap
                if (game.Children.TryGetValue("Remap", out YamlNode rmap))
                {
                    remap = rmap.ToString();
                }

                // Engine
                if (game.Children.TryGetValue("Engine", out YamlNode yeng))
                {
                    var eng = (YamlMappingNode)yeng;
                    if (eng.Children.TryGetValue("Type", out YamlNode type))
                    {
                        engineType = (EngineType)Enum.Parse(typeof(EngineType), type.ToString());
                    }
                    if (eng.Children.TryGetValue("ReverbType", out YamlNode rType))
                    {
                        reverbType = (ReverbType)Enum.Parse(typeof(ReverbType), rType.ToString());
                    }
                    if (eng.Children.TryGetValue("Reverb", out YamlNode reverb))
                    {
                        engineReverb = (byte)Utils.ParseValue(reverb.ToString());
                    }
                    if (eng.Children.TryGetValue("Volume", out YamlNode volume))
                    {
                        engineVolume = (byte)Utils.ParseValue(volume.ToString());
                    }
                    if (eng.Children.TryGetValue("TrackLimit", out YamlNode trackLim))
                    {
                        engineTrackLimit = (byte)Utils.ParseValue(trackLim.ToString());
                    }
                    if (eng.Children.TryGetValue("Frequency", out YamlNode frequency))
                    {
                        engineFrequency = (int)Utils.ParseValue(frequency.ToString());
                    }
                    if (eng.Children.TryGetValue("GoldenSunSynths", out YamlNode synths))
                    {
                        engineHasGoldenSunSynths = bool.Parse(synths.ToString());
                    }
                }
                var engine = new AnEngine(engineType, reverbType, engineReverb, engineVolume, engineTrackLimit, engineFrequency, engineHasGoldenSunSynths);

                // Load playlists
                playlists = new List <APlaylist>();
                if (game.Children.TryGetValue("Music", out YamlNode ymusic))
                {
                    var music = (YamlMappingNode)ymusic;
                    foreach (var kvp in music)
                    {
                        var songs = new List <ASong>();
                        foreach (var song in (YamlMappingNode)kvp.Value)
                        {
                            songs.Add(new ASong(short.Parse(song.Key.ToString()), song.Value.ToString())); // No hex values. It prevents putting in duplicates by having one hex and one dec of the same song index
                        }
                        playlists.Add(new APlaylist(kvp.Key.ToString(), songs.ToArray()));
                    }
                }

                // Full playlist
                if (!playlists.Any(p => p.Name == "Music"))
                {
                    playlists.Insert(0, new APlaylist("Music", playlists.Select(p => p.Songs).UniteAll().OrderBy(s => s.Index).ToArray()));
                }

                // If playlist is empty, add an empty entry
                for (int i = 0; i < playlists.Count; i++)
                {
                    if (playlists[i].Songs.Length == 0)
                    {
                        playlists[i] = new APlaylist(playlists[i].Name, new ASong[] { new ASong(0, "Playlist is empty.") });
                    }
                }

                Games.Add(code, new AGame(code, name, creator, engine, tables, tableSizes, playlists, remap,
                                          voiceTable, sampleTable, sampleTableSize));
            }
        }
Beispiel #6
0
 internal AnEngine(EngineType type, ReverbType reverbType, byte reverb, byte volume, uint frequency)
 {
     Type = type; ReverbType = reverbType; Reverb = reverb; Volume = volume; Frequency = frequency;
 }
Beispiel #7
0
        public Config(byte[] rom)
        {
            const string configFile = "MP2K.yaml";

            using (StreamReader fileStream = File.OpenText(configFile))
            {
                string gcv = string.Empty;
                try
                {
                    ROM      = rom;
                    Reader   = new EndianBinaryReader(new MemoryStream(rom));
                    GameCode = Reader.ReadString(4, 0xAC);
                    Version  = Reader.ReadByte(0xBC);
                    gcv      = $"{GameCode}_{Version:X2}";
                    var yaml = new YamlStream();
                    yaml.Load(fileStream);

                    var             mapping = (YamlMappingNode)yaml.Documents[0].RootNode;
                    YamlMappingNode game;
                    try
                    {
                        game = (YamlMappingNode)mapping.Children.GetValue(gcv);
                    }
                    catch (BetterKeyNotFoundException)
                    {
                        throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + string.Format(Strings.ErrorMLSSMP2KMissingGameCode, gcv)));
                    }

                    Name = game.Children.GetValue(nameof(Name)).ToString();

                    string[] songTables = game.Children.GetValue(nameof(SongTableOffsets)).ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (songTables.Length == 0)
                    {
                        throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyNoEntries, nameof(SongTableOffsets))));
                    }

                    if (game.Children.TryGetValue("Copy", out YamlNode copy))
                    {
                        try
                        {
                            game = (YamlMappingNode)mapping.Children.GetValue(copy);
                        }
                        catch (BetterKeyNotFoundException ex)
                        {
                            throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorMLSSMP2KCopyInvalidGameCode, ex.Key)));
                        }
                    }

                    string[] sizes = game.Children.GetValue(nameof(SongTableSizes)).ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (sizes.Length != songTables.Length)
                    {
                        throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorMLSSMP2KSongTableCounts, nameof(SongTableSizes), nameof(SongTableOffsets))));
                    }
                    SongTableOffsets = new int[songTables.Length];
                    SongTableSizes   = new long[songTables.Length];
                    for (int i = 0; i < songTables.Length; i++)
                    {
                        SongTableSizes[i]   = Util.Utils.ParseValue(nameof(SongTableSizes), sizes[i], 1, rom.Length - 1);
                        SongTableOffsets[i] = (int)Util.Utils.ParseValue(nameof(SongTableOffsets), songTables[i], 0, rom.Length - 1);
                    }

                    SampleRate = (int)game.GetValidValue(nameof(SampleRate), 0, Utils.FrequencyTable.Length - 1);
                    try
                    {
                        ReverbType = (ReverbType)Enum.Parse(typeof(ReverbType), game.Children.GetValue(nameof(ReverbType)).ToString());
                    }
                    catch (Exception ex) when(ex is ArgumentException || ex is OverflowException)
                    {
                        throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyInvalid, nameof(ReverbType))));
                    }
                    Reverb                = (byte)game.GetValidValue(nameof(Reverb), byte.MinValue, byte.MaxValue);
                    Volume                = (byte)game.GetValidValue(nameof(Volume), 0, 15);
                    HasGoldenSunSynths    = game.GetValidBoolean(nameof(HasGoldenSunSynths));
                    HasPokemonCompression = game.GetValidBoolean(nameof(HasPokemonCompression));
                    if (game.Children.TryGetValue(nameof(Remap), out YamlNode remap))
                    {
                        Remap = remap.ToString();
                    }

                    if (game.Children.TryGetValue(nameof(Playlists), out YamlNode _playlists))
                    {
                        var playlists = (YamlMappingNode)_playlists;
                        foreach (KeyValuePair <YamlNode, YamlNode> kvp in playlists)
                        {
                            string name  = kvp.Key.ToString();
                            var    songs = new List <Song>();
                            foreach (KeyValuePair <YamlNode, YamlNode> song in (YamlMappingNode)kvp.Value)
                            {
                                long songIndex = Util.Utils.ParseValue(string.Format(Strings.ConfigKeySubkey, nameof(Playlists)), song.Key.ToString(), 0, long.MaxValue);
                                if (songs.Any(s => s.Index == songIndex))
                                {
                                    throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorMLSSMP2KSongRepeated, name, songIndex)));
                                }
                                songs.Add(new Song(songIndex, song.Value.ToString()));
                            }
                            Playlists.Add(new Playlist(name, songs));
                        }
                    }

                    // The complete playlist
                    if (!Playlists.Any(p => p.Name == "Music"))
                    {
                        Playlists.Insert(0, new Playlist(Strings.PlaylistMusic, Playlists.SelectMany(p => p.Songs).Distinct().OrderBy(s => s.Index)));
                    }
                }
                catch (BetterKeyNotFoundException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + string.Format(Strings.ErrorConfigKeyMissing, ex.Key)));
                }
                catch (InvalidValueException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorMLSSMP2KParseGameCode, gcv, configFile, Environment.NewLine + ex.Message));
                }
                catch (YamlDotNet.Core.YamlException ex)
                {
                    throw new Exception(string.Format(Strings.ErrorParseConfig, configFile, Environment.NewLine + ex.Message));
                }
            }
        }
Beispiel #8
0
		public static extern IntPtr		iplEstimateReverb(IntPtr estimator, ReverbType type, Vector3 position);
Beispiel #9
0
		public static extern IntPtr		iplGetBakedReverb(IntPtr grid, ReverbType type, Vector3 position);