/// <summary /> public SoundService() { Service = this; _ambientReverb = ReverbType.NoReverb; _distanceFactor = 1.0f; _dopplerScale = 1.0f; _rolloffScale = 1.0f; }
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; } } }
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)); } } }
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; }
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)); } }
internal AnEngine(EngineType type, ReverbType reverbType, byte reverb, byte volume, uint frequency) { Type = type; ReverbType = reverbType; Reverb = reverb; Volume = volume; Frequency = frequency; }
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)); } } }
public static extern IntPtr iplEstimateReverb(IntPtr estimator, ReverbType type, Vector3 position);
public static extern IntPtr iplGetBakedReverb(IntPtr grid, ReverbType type, Vector3 position);