diff --git a/Assembly-CSharp/Assembly-CSharp.csproj b/Assembly-CSharp/Assembly-CSharp.csproj
index f894cebd1..e17b7f0e0 100644
--- a/Assembly-CSharp/Assembly-CSharp.csproj
+++ b/Assembly-CSharp/Assembly-CSharp.csproj
@@ -265,6 +265,7 @@
+
diff --git a/Assembly-CSharp/Global/Sound/SaXAudio/AudioEffectManager.cs b/Assembly-CSharp/Global/Sound/SaXAudio/AudioEffectManager.cs
index 6e29833fe..093d0c796 100644
--- a/Assembly-CSharp/Global/Sound/SaXAudio/AudioEffectManager.cs
+++ b/Assembly-CSharp/Global/Sound/SaXAudio/AudioEffectManager.cs
@@ -13,7 +13,7 @@ namespace Global.Sound.SaXAudio
{
public class AudioEffectManager
{
- private const String FILENAME = "AudioEffects.txt";
+ private const String FILENAME = "StreamingAssets/Data/Voices/AudioEffects.csv";
private static Dictionary fieldIDPresets = new Dictionary();
private static Dictionary battleIDPresets = new Dictionary();
@@ -21,7 +21,7 @@ public class AudioEffectManager
private static Dictionary resourceIDPresets = new Dictionary();
private static List conditionalPresets = new List();
private static Dictionary unlistedPresets = new Dictionary();
- private static EffectPreset? currentPreset = null;
+ private static EffectPreset currentPreset = null;
private static Boolean initialized = false;
private static FileSystemWatcher watcher = null;
@@ -48,7 +48,7 @@ public static void ApplyFieldEffects(Int32 fieldID)
if (!initialized) Init();
}
- if (fieldIDPresets.TryGetValue(fieldID, out EffectPreset preset) && ApplyPreset(ref preset))
+ if (fieldIDPresets.TryGetValue(fieldID, out EffectPreset preset) && ApplyPreset(preset))
{
currentPreset = preset;
Log.Message($"[AudioEffectManager] Applied preset '{preset.Name}' to field {fieldID}");
@@ -66,14 +66,14 @@ public static void ApplyBattleEffects(Int32 battleID, Int32 battleBgID)
if (!initialized) Init();
}
- if (battleIDPresets.TryGetValue(battleID, out EffectPreset preset) && ApplyPreset(ref preset))
+ if (battleIDPresets.TryGetValue(battleID, out EffectPreset preset) && ApplyPreset(preset))
{
currentPreset = preset;
Log.Message($"[AudioEffectManager] Applied preset '{preset.Name}' to battle {battleID}");
return;
}
- if (battleBgIDPresets.TryGetValue(battleBgID, out preset) && ApplyPreset(ref preset))
+ if (battleBgIDPresets.TryGetValue(battleBgID, out preset) && ApplyPreset(preset))
{
currentPreset = preset;
Log.Message($"[AudioEffectManager] Applied preset '{preset.Name}' to battle background {battleBgID}");
@@ -82,42 +82,46 @@ public static void ApplyBattleEffects(Int32 battleID, Int32 battleBgID)
ResetEffects();
}
- public static EffectPreset? GetPreset(SoundProfile profile, Int32 bus)
+ public static EffectPreset GetPreset(SoundProfile profile, Int32 bus)
{
if (!IsSaXAudio || !initialized)
return null;
- EffectPreset? preset = null;
- if (resourceIDPresets.ContainsKey(profile.ResourceID))
- preset = resourceIDPresets[profile.ResourceID];
+ EffectPreset preset = null;
- // resourceIDs gets priority
- if (preset != null && (String.IsNullOrEmpty(preset.Value.Condition) || EvaluatePresetCondition(profile, preset.Value.Condition, preset.Value.Name)))
- return preset;
+ // 1. resourceIDs gets priority
+ if (resourceIDPresets.TryGetValue(profile.ResourceID, out preset))
+ if (String.IsNullOrEmpty(preset.Condition) || EvaluatePresetCondition(profile, preset.CompiledCondition, preset.Name))
+ return preset;
- // then conditional
+ // 2. then conditional
for (Int32 i = 0; i < conditionalPresets.Count; i++)
{
preset = conditionalPresets[i];
- if ((preset.Value.Layers == EffectPreset.Layer.None || preset.Value.IsBusInLayers(bus)) && EvaluatePresetCondition(profile, preset.Value.Condition, preset.Value.Name))
+
+ Boolean isBusValid = preset.Layers == EffectPreset.Layer.None || preset.IsBusInLayers(bus);
+ if (isBusValid && EvaluatePresetCondition(profile, preset.CompiledCondition, preset.Name))
return preset;
}
- // then filter current preset
+ // 3. then filter current preset
preset = currentPreset;
- if (preset != null && preset.Value.IsBusInLayers(bus) && !String.IsNullOrEmpty(preset.Value.Condition) && !EvaluatePresetCondition(profile, preset.Value.Condition, preset.Value.Name))
- return new EffectPreset(); // empty preset because we want to exclude that particular sound
+ if (preset != null && preset.IsBusInLayers(bus))
+ {
+ if (!String.IsNullOrEmpty(preset.Condition) && !EvaluatePresetCondition(profile, preset.CompiledCondition, preset.Name))
+ return new EffectPreset(); // empty preset because we want to exclude that particular sound
+ }
return null;
}
- public static EffectPreset? GetUnlistedPreset(String presetName)
+ public static EffectPreset GetUnlistedPreset(String presetName)
{
if (!IsSaXAudio || !initialized || !unlistedPresets.ContainsKey(presetName)) return null;
return unlistedPresets[presetName];
}
- public static EffectPreset? FindPreset(String presetName)
+ public static EffectPreset FindPreset(String presetName)
{
if (!IsSaXAudio || !initialized) return null;
@@ -157,12 +161,10 @@ public static void ApplyBattleEffects(Int32 battleID, Int32 battleBgID)
return null;
}
- public static Boolean EvaluatePresetCondition(SoundProfile profile, String condition, String presetName)
+ public static Boolean EvaluatePresetCondition(SoundProfile profile, Expression c, String presetName)
{
- Expression c = new Expression(condition);
- c.EvaluateFunction += NCalcUtility.commonNCalcFunctions;
- c.EvaluateParameter += NCalcUtility.commonNCalcParameters;
- c.EvaluateParameter += NCalcUtility.worldNCalcParameters;
+ if (c == null) return false;
+
c.Parameters["SoundIndex"] = profile.SoundIndex;
c.Parameters["ResourceID"] = profile.ResourceID;
c.Parameters["SoundProfileType"] = profile.SoundProfileType;
@@ -181,7 +183,7 @@ public static Boolean EvaluatePresetCondition(SoundProfile profile, String condi
}
catch (Exception e)
{
- Log.Error($"[AudioEffectManager] Couldn't evaluate condition: '{condition.Trim()}' in preset '{presetName}'");
+ Log.Error($"[AudioEffectManager] Couldn't evaluate condition in preset '{presetName}'");
Log.Error(e);
}
@@ -254,7 +256,7 @@ private static void Init()
{
if (folder.TryFindAssetInModOnDisc(FILENAME, out String fullPath))
{
- var presets = LoadPresets($"{Path.GetDirectoryName(fullPath)}\\");
+ var presets = LoadPresets(folder.FolderPath);
foreach (var preset in presets.Values)
{
Boolean listed = false;
@@ -295,7 +297,7 @@ private static void Init()
if (watcher == null)
{
- watcher = new FileSystemWatcher("./", $"*{FILENAME}");
+ watcher = new FileSystemWatcher("./", Path.GetFileName(FILENAME));
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += (sender, e) =>
@@ -309,19 +311,19 @@ private static void Init()
initialized = true;
}
- private static Boolean ApplyPreset(ref EffectPreset preset)
+ private static Boolean ApplyPreset(EffectPreset preset)
{
SdLibAPIWithSaXAudio saXAudio = ISdLibAPIProxy.Instance as SdLibAPIWithSaXAudio;
- if ((preset.Layers & EffectPreset.Layer.Music) != 0) ApplyPresetOnBus(ref preset, saXAudio.BusMusic);
- if ((preset.Layers & EffectPreset.Layer.Ambient) != 0) ApplyPresetOnBus(ref preset, saXAudio.BusAmbient);
- if ((preset.Layers & EffectPreset.Layer.SoundEffect) != 0) ApplyPresetOnBus(ref preset, saXAudio.BusSoundEffect);
- if ((preset.Layers & EffectPreset.Layer.Voice) != 0) ApplyPresetOnBus(ref preset, saXAudio.BusVoice);
+ if ((preset.Layers & EffectPreset.Layer.Music) != 0) ApplyPresetOnBus(preset, saXAudio.BusMusic);
+ if ((preset.Layers & EffectPreset.Layer.Ambient) != 0) ApplyPresetOnBus(preset, saXAudio.BusAmbient);
+ if ((preset.Layers & EffectPreset.Layer.SoundEffect) != 0) ApplyPresetOnBus(preset, saXAudio.BusSoundEffect);
+ if ((preset.Layers & EffectPreset.Layer.Voice) != 0) ApplyPresetOnBus(preset, saXAudio.BusVoice);
return true;
}
- private static void ApplyPresetOnBus(ref EffectPreset preset, Int32 bus)
+ private static void ApplyPresetOnBus(EffectPreset preset, Int32 bus)
{
Boolean reverb = (preset.Effects & EffectPreset.Effect.Reverb) != 0;
Boolean eq = (preset.Effects & EffectPreset.Effect.Eq) != 0;
@@ -338,208 +340,6 @@ private static void ApplyPresetOnBus(ref EffectPreset preset, Int32 bus)
else SaXAudio.SetVolume(bus, 1f, 0, true);
}
- public struct EffectPreset
- {
- public enum Effect : Byte
- {
- None = 0,
- Reverb = 1,
- Eq = 1 << 1,
- Echo = 1 << 2,
- Volume = 1 << 3,
- All = Reverb | Eq | Echo | Volume
- }
-
- public enum Layer : Byte
- {
- None = 0,
- Music = 1,
- Ambient = 1 << 1,
- SoundEffect = 1 << 2,
- Voice = 1 << 3,
- All = Music | Ambient | SoundEffect | Voice
- }
-
- public Boolean IsBusInLayers(Int32 bus)
- {
- if (!IsSaXAudio || Layers == Layer.None)
- return false;
-
- SdLibAPIWithSaXAudio saXAudio = ISdLibAPIProxy.Instance as SdLibAPIWithSaXAudio;
-
- if ((Layers & Layer.Music) != 0 && bus == saXAudio.BusMusic)
- return true;
- if ((Layers & Layer.Ambient) != 0 && bus == saXAudio.BusAmbient)
- return true;
- if ((Layers & Layer.SoundEffect) != 0 && bus == saXAudio.BusSoundEffect)
- return true;
- if ((Layers & Layer.Voice) != 0 && bus == saXAudio.BusVoice)
- return true;
- return false;
- }
-
- public String Name = "";
- public Effect Effects = Effect.None;
- public SaXAudio.ReverbParameters Reverb = new SaXAudio.ReverbParameters();
- public SaXAudio.EqParameters Eq = new SaXAudio.EqParameters();
- public SaXAudio.EchoParameters Echo = new SaXAudio.EchoParameters();
- public Single Volume = 1f;
-
- public Layer Layers = Layer.None;
- public HashSet FieldIDs = new HashSet();
- public HashSet ResourceIDs = new HashSet();
- public HashSet BattleIDs = new HashSet();
- public HashSet BattleBgIDs = new HashSet();
-
- public String Condition = "";
-
- public EffectPreset() { }
- public EffectPreset(String str)
- {
- String[] tokens = str.Split(';');
- Int32 i = 0;
- Name = tokens[i++];
- Effects = (Effect)Byte.Parse(tokens[i++]);
-
- FieldInfo[] fields = typeof(SaXAudio.ReverbParameters).GetFields();
- object reverb = Reverb;
- foreach (FieldInfo field in fields)
- {
- field.SetValue(reverb, Convert.ChangeType(tokens[i++], field.FieldType, CultureInfo.InvariantCulture));
- }
- Reverb = (SaXAudio.ReverbParameters)reverb;
-
- fields = typeof(SaXAudio.EqParameters).GetFields();
- object eq = Eq;
- foreach (FieldInfo field in fields)
- {
- field.SetValue(eq, Convert.ChangeType(tokens[i++], field.FieldType, CultureInfo.InvariantCulture));
- }
- Eq = (SaXAudio.EqParameters)eq;
-
- fields = typeof(SaXAudio.EchoParameters).GetFields();
- object echo = Echo;
- foreach (FieldInfo field in fields)
- {
- field.SetValue(echo, Convert.ChangeType(tokens[i++], field.FieldType, CultureInfo.InvariantCulture));
- }
- Echo = (SaXAudio.EchoParameters)echo;
-
- Volume = Single.Parse(tokens[i++]);
-
- if (i == tokens.Length) return;
-
- Layers = (Layer)Byte.Parse(tokens[i++]);
-
- String[] ids = tokens[i++].Split('|');
- if (ids.Length > 0)
- {
- FieldIDs.Clear();
- foreach (String id in ids)
- {
- if (id.Length > 0)
- FieldIDs.Add(Int32.Parse(id));
- }
- }
-
- ids = tokens[i++].Split('|');
- if (ids.Length > 0)
- {
- BattleIDs.Clear();
- foreach (String id in ids)
- {
- if (id.Length > 0)
- BattleIDs.Add(Int32.Parse(id));
- }
- }
-
- ids = tokens[i++].Split('|');
- if (ids.Length > 0)
- {
- BattleBgIDs.Clear();
- foreach (String id in ids)
- {
- if (id.Length > 0)
- BattleBgIDs.Add(Int32.Parse(id));
- }
- }
-
- ids = tokens[i++].Split('|');
- if (ids.Length > 0)
- {
- ResourceIDs.Clear();
- foreach (String id in ids)
- {
- if (id.Length > 0)
- ResourceIDs.Add(id);
- }
- }
-
- Condition = tokens[i++].Replace('\x0A', ';');
- }
-
- public override readonly String ToString()
- {
- StringBuilder builder = new StringBuilder();
- const Char separator = ';';
- builder.Append(Name);
- builder.Append(separator);
- builder.Append((Byte)Effects);
-
- FieldInfo[] fields = typeof(SaXAudio.ReverbParameters).GetFields();
- foreach (FieldInfo field in fields)
- {
- builder.Append(separator);
- builder.Append((String)Convert.ChangeType(field.GetValue(Reverb), typeof(String), CultureInfo.InvariantCulture));
- }
-
- fields = typeof(SaXAudio.EqParameters).GetFields();
- foreach (FieldInfo field in fields)
- {
- builder.Append(separator);
- builder.Append((String)Convert.ChangeType(field.GetValue(Eq), typeof(String), CultureInfo.InvariantCulture));
- }
-
- fields = typeof(SaXAudio.EchoParameters).GetFields();
- foreach (FieldInfo field in fields)
- {
- builder.Append(separator);
- builder.Append((String)Convert.ChangeType(field.GetValue(Echo), typeof(String), CultureInfo.InvariantCulture));
- }
-
- builder.Append(separator);
- builder.Append(Volume);
-
- builder.Append(separator);
- builder.Append((Byte)Layers);
-
- builder.Append(separator);
- builder.Append(String.Join("|", FieldIDs.Select(x => x.ToString()).ToArray()));
-
- builder.Append(separator);
- builder.Append(String.Join("|", BattleIDs.Select(x => x.ToString()).ToArray()));
-
- builder.Append(separator);
- builder.Append(String.Join("|", BattleBgIDs.Select(x => x.ToString()).ToArray()));
-
- builder.Append(separator);
- builder.Append(String.Join("|", ResourceIDs.ToArray()));
-
- builder.Append(separator);
- builder.Append(Condition.Trim().Replace(';', '\x0A'));
-
- return builder.ToString();
- }
-
- public void RemoveIDs()
- {
- FieldIDs = null;
- BattleIDs = null;
- BattleBgIDs = null;
- ResourceIDs = null;
- }
- }
-
public static SortedDictionary LoadPresets(String modLocation, Boolean backup = false)
{
SortedDictionary presets = new SortedDictionary();
@@ -554,10 +354,16 @@ public static SortedDictionary LoadPresets(String modLocat
{
if (line.Length == 0 || line.StartsWith("#"))
continue;
- EffectPreset preset = new EffectPreset(line);
- presets.Add(preset.Name, preset);
+
+ EffectPreset preset = new EffectPreset();
+ preset.ParseEntry(line.Split(';'), null);
+
+ if (!string.IsNullOrEmpty(preset.Name))
+ {
+ presets[preset.Name] = preset;
+ }
}
- Log.Message($"[AudioEffectManager] Loaded {mod} presets");
+ Log.Message($"[AudioEffectManager] Loaded {mod} presets from CSV");
}
catch (Exception e)
{
@@ -573,13 +379,18 @@ public static void SavePresets(SortedDictionary presets, S
{
String mod = Path.GetDirectoryName(modLocation);
List lines = new List();
+
+ lines.Add("# ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
+ lines.Add("# Name;Effects;Reverb.WetDryMix;Reverb.ReflectionsDelay;Reverb.ReverbDelay;Reverb.RearDelay;Reverb.SideDelay;Reverb.PositionLeft;Reverb.PositionRight;Reverb.PositionMatrixLeft;Reverb.PositionMatrixRight;Reverb.EarlyDiffusion;Reverb.LateDiffusion;Reverb.LowEQGain;Reverb.LowEQCutoff;Reverb.HighEQGain;Reverb.HighEQCutoff;Reverb.RoomFilterFreq;Reverb.RoomFilterMain;Reverb.RoomFilterHF;Reverb.ReflectionsGain;Reverb.ReverbGain;Reverb.DecayTime;Reverb.Density;Reverb.RoomSize;Reverb.DisableLateField;Eq.FrequencyCenter0;Eq.Gain0;Eq.Bandwidth0;Eq.FrequencyCenter1;Eq.Gain1;Eq.Bandwidth1;Eq.FrequencyCenter2;Eq.Gain2;Eq.Bandwidth2;Eq.FrequencyCenter3;Eq.Gain3;Eq.Bandwidth3;Echo.WetDryMix;Echo.Feedback;Echo.Delay;Volume;Layers;FieldIDs;BattleIDs;BattleBgIDs;ResourceIDs;NCalcCondition");
+ lines.Add("# String;Byte;Single;UInt32;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Byte;Single;Single;Single;Single;Single;Single;Single;Single;Boolean;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Single;Byte;String;String;String;String;String");
+ lines.Add("# ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
+
foreach (EffectPreset effectPreset in presets.Values)
- {
lines.Add(effectPreset.ToString());
- }
+
String path = Path.Combine(modLocation, $"{FILENAME}{(backup ? ".bak" : "")}");
File.WriteAllLines(path, lines.ToArray());
- Log.Message($"[AudioEffectManager] Saved {mod} presets");
+ Log.Message($"[AudioEffectManager] Saved {mod} presets to CSV");
}
catch (Exception e)
{
diff --git a/Assembly-CSharp/Global/Sound/SaXAudio/EffectPreset.cs b/Assembly-CSharp/Global/Sound/SaXAudio/EffectPreset.cs
new file mode 100644
index 000000000..cb25b1181
--- /dev/null
+++ b/Assembly-CSharp/Global/Sound/SaXAudio/EffectPreset.cs
@@ -0,0 +1,309 @@
+using Memoria.Prime.CSV;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using NCalc;
+
+namespace Global.Sound.SaXAudio
+{
+ public sealed class EffectPreset : ICsvEntry
+ {
+ public enum Effect : Byte
+ {
+ None = 0,
+ Reverb = 1,
+ Eq = 1 << 1,
+ Echo = 1 << 2,
+ Volume = 1 << 3,
+ All = Reverb | Eq | Echo | Volume
+ }
+
+ public enum Layer : Byte
+ {
+ None = 0,
+ Music = 1,
+ Ambient = 1 << 1,
+ SoundEffect = 1 << 2,
+ Voice = 1 << 3,
+ All = Music | Ambient | SoundEffect | Voice
+ }
+
+ public String Name = "";
+ public Effect Effects = Effect.None;
+ public SaXAudio.ReverbParameters Reverb = new SaXAudio.ReverbParameters();
+ public SaXAudio.EqParameters Eq = new SaXAudio.EqParameters();
+ public SaXAudio.EchoParameters Echo = new SaXAudio.EchoParameters();
+ public Single Volume = 1f;
+
+ public Layer Layers = Layer.None;
+ public HashSet FieldIDs = new HashSet();
+ public HashSet BattleIDs = new HashSet();
+ public HashSet BattleBgIDs = new HashSet();
+ public HashSet ResourceIDs = new HashSet();
+ public String Condition = "";
+
+ public Expression CompiledCondition { get; private set; } = null;
+
+ public EffectPreset() { }
+
+ public Boolean IsBusInLayers(Int32 bus)
+ {
+ if (!AudioEffectManager.IsSaXAudio || Layers == Layer.None)
+ return false;
+
+ SdLibAPIWithSaXAudio saXAudio = ISdLibAPIProxy.Instance as SdLibAPIWithSaXAudio;
+ if (saXAudio == null) return false;
+
+ if ((Layers & Layer.Music) != 0 && bus == saXAudio.BusMusic)
+ return true;
+ if ((Layers & Layer.Ambient) != 0 && bus == saXAudio.BusAmbient)
+ return true;
+ if ((Layers & Layer.SoundEffect) != 0 && bus == saXAudio.BusSoundEffect)
+ return true;
+ if ((Layers & Layer.Voice) != 0 && bus == saXAudio.BusVoice)
+ return true;
+ return false;
+ }
+
+ public void RemoveIDs()
+ {
+ FieldIDs = null;
+ BattleIDs = null;
+ BattleBgIDs = null;
+ ResourceIDs = null;
+ }
+
+ public static Expression PrepareExpression(String code)
+ {
+ Expression e = new Expression(code);
+ e.EvaluateFunction += NCalcUtility.commonNCalcFunctions;
+ e.EvaluateParameter += NCalcUtility.commonNCalcParameters;
+ e.EvaluateParameter += NCalcUtility.worldNCalcParameters;
+ return e;
+ }
+
+ public void ParseEntry(String[] raw, CsvMetaData metadata)
+ {
+ if (raw.Length < 47) return;
+
+ Name = raw[0];
+ Effects = (Effect)Byte.Parse(raw[1]);
+
+ Reverb.WetDryMix = Single.Parse(raw[2], CultureInfo.InvariantCulture);
+ Reverb.ReflectionsDelay = UInt32.Parse(raw[3], CultureInfo.InvariantCulture);
+ Reverb.ReverbDelay = Byte.Parse(raw[4], CultureInfo.InvariantCulture);
+ Reverb.RearDelay = Byte.Parse(raw[5], CultureInfo.InvariantCulture);
+ Reverb.SideDelay = Byte.Parse(raw[6], CultureInfo.InvariantCulture);
+ Reverb.PositionLeft = Byte.Parse(raw[7], CultureInfo.InvariantCulture);
+ Reverb.PositionRight = Byte.Parse(raw[8], CultureInfo.InvariantCulture);
+ Reverb.PositionMatrixLeft = Byte.Parse(raw[9], CultureInfo.InvariantCulture);
+ Reverb.PositionMatrixRight = Byte.Parse(raw[10], CultureInfo.InvariantCulture);
+ Reverb.EarlyDiffusion = Byte.Parse(raw[11], CultureInfo.InvariantCulture);
+ Reverb.LateDiffusion = Byte.Parse(raw[12], CultureInfo.InvariantCulture);
+ Reverb.LowEQGain = Byte.Parse(raw[13], CultureInfo.InvariantCulture);
+ Reverb.LowEQCutoff = Byte.Parse(raw[14], CultureInfo.InvariantCulture);
+ Reverb.HighEQGain = Byte.Parse(raw[15], CultureInfo.InvariantCulture);
+ Reverb.HighEQCutoff = Byte.Parse(raw[16], CultureInfo.InvariantCulture);
+ Reverb.RoomFilterFreq = Single.Parse(raw[17], CultureInfo.InvariantCulture);
+ Reverb.RoomFilterMain = Single.Parse(raw[18], CultureInfo.InvariantCulture);
+ Reverb.RoomFilterHF = Single.Parse(raw[19], CultureInfo.InvariantCulture);
+ Reverb.ReflectionsGain = Single.Parse(raw[20], CultureInfo.InvariantCulture);
+ Reverb.ReverbGain = Single.Parse(raw[21], CultureInfo.InvariantCulture);
+ Reverb.DecayTime = Single.Parse(raw[22], CultureInfo.InvariantCulture);
+ Reverb.Density = Single.Parse(raw[23], CultureInfo.InvariantCulture);
+ Reverb.RoomSize = Single.Parse(raw[24], CultureInfo.InvariantCulture);
+ Reverb.DisableLateField = Boolean.Parse(raw[25]);
+
+ Eq.FrequencyCenter0 = Single.Parse(raw[26], CultureInfo.InvariantCulture);
+ Eq.Gain0 = Single.Parse(raw[27], CultureInfo.InvariantCulture);
+ Eq.Bandwidth0 = Single.Parse(raw[28], CultureInfo.InvariantCulture);
+ Eq.FrequencyCenter1 = Single.Parse(raw[29], CultureInfo.InvariantCulture);
+ Eq.Gain1 = Single.Parse(raw[30], CultureInfo.InvariantCulture);
+ Eq.Bandwidth1 = Single.Parse(raw[31], CultureInfo.InvariantCulture);
+ Eq.FrequencyCenter2 = Single.Parse(raw[32], CultureInfo.InvariantCulture);
+ Eq.Gain2 = Single.Parse(raw[33], CultureInfo.InvariantCulture);
+ Eq.Bandwidth2 = Single.Parse(raw[34], CultureInfo.InvariantCulture);
+ Eq.FrequencyCenter3 = Single.Parse(raw[35], CultureInfo.InvariantCulture);
+ Eq.Gain3 = Single.Parse(raw[36], CultureInfo.InvariantCulture);
+ Eq.Bandwidth3 = Single.Parse(raw[37], CultureInfo.InvariantCulture);
+
+ Echo.WetDryMix = Single.Parse(raw[38], CultureInfo.InvariantCulture);
+ Echo.Feedback = Single.Parse(raw[39], CultureInfo.InvariantCulture);
+ Echo.Delay = Single.Parse(raw[40], CultureInfo.InvariantCulture);
+
+ Volume = Single.Parse(raw[41], CultureInfo.InvariantCulture);
+ Layers = (Layer)Byte.Parse(raw[42]);
+
+ String[] ids;
+
+ ids = raw[43].Split('|');
+ if (ids.Length > 0)
+ {
+ FieldIDs.Clear();
+ foreach (String id in ids)
+ if (id.Length > 0) FieldIDs.Add(Int32.Parse(id));
+ }
+
+ ids = raw[44].Split('|');
+ if (ids.Length > 0)
+ {
+ BattleIDs.Clear();
+ foreach (String id in ids)
+ if (id.Length > 0) BattleIDs.Add(Int32.Parse(id));
+ }
+
+ ids = raw[45].Split('|');
+ if (ids.Length > 0)
+ {
+ BattleBgIDs.Clear();
+ foreach (String id in ids)
+ if (id.Length > 0) BattleBgIDs.Add(Int32.Parse(id));
+ }
+
+ ids = raw[46].Split('|');
+ if (ids.Length > 0)
+ {
+ ResourceIDs.Clear();
+ foreach (String id in ids)
+ if (id.Length > 0) ResourceIDs.Add(id);
+ }
+
+ Condition = raw[47];
+ if (!String.IsNullOrEmpty(Condition))
+ {
+ try
+ {
+ CompiledCondition = PrepareExpression(Condition);
+ }
+ catch (Exception e)
+ {
+ Memoria.Prime.Log.Warning($"[EffectPreset] Failed to compile condition '{Condition}' for preset '{Name}': {e.Message}");
+ }
+ }
+ }
+
+ public void WriteEntry(CsvWriter writer, CsvMetaData metadata)
+ {
+ writer.String(Name);
+ writer.Byte((Byte)Effects);
+
+ // Reverb
+ writer.String(Reverb.WetDryMix.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.ReflectionsDelay.ToString(CultureInfo.InvariantCulture));
+ writer.Byte(Reverb.ReverbDelay);
+ writer.Byte(Reverb.RearDelay);
+ writer.Byte(Reverb.SideDelay);
+ writer.Byte(Reverb.PositionLeft);
+ writer.Byte(Reverb.PositionRight);
+ writer.Byte(Reverb.PositionMatrixLeft);
+ writer.Byte(Reverb.PositionMatrixRight);
+ writer.Byte(Reverb.EarlyDiffusion);
+ writer.Byte(Reverb.LateDiffusion);
+ writer.Byte(Reverb.LowEQGain);
+ writer.Byte(Reverb.LowEQCutoff);
+ writer.Byte(Reverb.HighEQGain);
+ writer.Byte(Reverb.HighEQCutoff);
+ writer.String(Reverb.RoomFilterFreq.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.RoomFilterMain.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.RoomFilterHF.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.ReflectionsGain.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.ReverbGain.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.DecayTime.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.Density.ToString(CultureInfo.InvariantCulture));
+ writer.String(Reverb.RoomSize.ToString(CultureInfo.InvariantCulture));
+ writer.Boolean(Reverb.DisableLateField);
+
+ // EQ
+ writer.String(Eq.FrequencyCenter0.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Gain0.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Bandwidth0.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.FrequencyCenter1.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Gain1.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Bandwidth1.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.FrequencyCenter2.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Gain2.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Bandwidth2.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.FrequencyCenter3.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Gain3.ToString(CultureInfo.InvariantCulture));
+ writer.String(Eq.Bandwidth3.ToString(CultureInfo.InvariantCulture));
+
+ // Echo
+ writer.String(Echo.WetDryMix.ToString(CultureInfo.InvariantCulture));
+ writer.String(Echo.Feedback.ToString(CultureInfo.InvariantCulture));
+ writer.String(Echo.Delay.ToString(CultureInfo.InvariantCulture));
+
+ // Volume & Layers
+ writer.String(Volume.ToString(CultureInfo.InvariantCulture));
+ writer.Byte((Byte)Layers);
+
+ writer.String(String.Join("|", FieldIDs.Select(x => x.ToString()).ToArray()));
+ writer.String(String.Join("|", BattleIDs.Select(x => x.ToString()).ToArray()));
+ writer.String(String.Join("|", BattleBgIDs.Select(x => x.ToString()).ToArray()));
+ writer.String(String.Join("|", ResourceIDs.ToArray()));
+
+ writer.String("");
+ }
+
+ public override string ToString()
+ {
+ List raw = new List();
+
+ raw.Add(Name);
+ raw.Add(((Byte)Effects).ToString());
+
+ raw.Add(Reverb.WetDryMix.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.ReflectionsDelay.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.ReverbDelay.ToString());
+ raw.Add(Reverb.RearDelay.ToString());
+ raw.Add(Reverb.SideDelay.ToString());
+ raw.Add(Reverb.PositionLeft.ToString());
+ raw.Add(Reverb.PositionRight.ToString());
+ raw.Add(Reverb.PositionMatrixLeft.ToString());
+ raw.Add(Reverb.PositionMatrixRight.ToString());
+ raw.Add(Reverb.EarlyDiffusion.ToString());
+ raw.Add(Reverb.LateDiffusion.ToString());
+ raw.Add(Reverb.LowEQGain.ToString());
+ raw.Add(Reverb.LowEQCutoff.ToString());
+ raw.Add(Reverb.HighEQGain.ToString());
+ raw.Add(Reverb.HighEQCutoff.ToString());
+ raw.Add(Reverb.RoomFilterFreq.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.RoomFilterMain.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.RoomFilterHF.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.ReflectionsGain.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.ReverbGain.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.DecayTime.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.Density.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.RoomSize.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Reverb.DisableLateField.ToString());
+
+ raw.Add(Eq.FrequencyCenter0.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Gain0.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Bandwidth0.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.FrequencyCenter1.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Gain1.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Bandwidth1.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.FrequencyCenter2.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Gain2.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Bandwidth2.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.FrequencyCenter3.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Gain3.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Eq.Bandwidth3.ToString(CultureInfo.InvariantCulture));
+
+ raw.Add(Echo.WetDryMix.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Echo.Feedback.ToString(CultureInfo.InvariantCulture));
+ raw.Add(Echo.Delay.ToString(CultureInfo.InvariantCulture));
+
+ raw.Add(Volume.ToString(CultureInfo.InvariantCulture));
+ raw.Add(((Byte)Layers).ToString());
+
+ raw.Add(String.Join("|", FieldIDs.Select(x => x.ToString()).ToArray()));
+ raw.Add(String.Join("|", BattleIDs.Select(x => x.ToString()).ToArray()));
+ raw.Add(String.Join("|", BattleBgIDs.Select(x => x.ToString()).ToArray()));
+ raw.Add(String.Join("|", ResourceIDs.ToArray()));
+ raw.Add(Condition);
+
+ return String.Join(";", raw.ToArray());
+ }
+ }
+}
diff --git a/Assembly-CSharp/Global/Sound/SaXAudio/SdLibAPIWithSaXAudio.cs b/Assembly-CSharp/Global/Sound/SaXAudio/SdLibAPIWithSaXAudio.cs
index cf1801560..09176b461 100644
--- a/Assembly-CSharp/Global/Sound/SaXAudio/SdLibAPIWithSaXAudio.cs
+++ b/Assembly-CSharp/Global/Sound/SaXAudio/SdLibAPIWithSaXAudio.cs
@@ -158,7 +158,7 @@ public override Int32 SdSoundSystem_CreateSound(Int32 bankID)
break;
}
- AudioEffectManager.EffectPreset? preset = AudioEffectManager.GetPreset(data.Profile, busID);
+ EffectPreset preset = AudioEffectManager.GetPreset(data.Profile, busID);
if (preset != null && busID != 0)
{
Log.Message($"[AudioEffectManager] Filtered '{data.Profile.ResourceID}' from bus {busID}");
@@ -178,7 +178,7 @@ public override Int32 SdSoundSystem_CreateSound(Int32 bankID)
}
if (preset != null)
- AudioEffectManager.ApplyPresetOnSound(preset.Value, soundID, data.Profile.Name);
+ AudioEffectManager.ApplyPresetOnSound(preset, soundID, data.Profile.Name);
if (soundID > 0)
sounds[soundID] = bankID;
diff --git a/Assembly-CSharp/SoundDebugRoom/SoundView.cs b/Assembly-CSharp/SoundDebugRoom/SoundView.cs
index 0f6998155..790a8ad88 100644
--- a/Assembly-CSharp/SoundDebugRoom/SoundView.cs
+++ b/Assembly-CSharp/SoundDebugRoom/SoundView.cs
@@ -1,6 +1,7 @@
using Assets.Scripts.Common;
using Assets.Sources.Scripts.Common;
using Global.Sound.SaXAudio;
+using Memoria.Data;
using Memoria.Prime;
using System;
using System.Collections.Generic;
@@ -359,6 +360,7 @@ private void BuildSelectorManager(Single width)
if (GUILayout.Button("Sound Effect"))
{
soundViewController.SetActiveSoundType(SoundProfileType.SoundEffect);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
if (GUILayout.Button("BGM"))
@@ -367,21 +369,25 @@ private void BuildSelectorManager(Single width)
soundViewController.SetPanning(PanningPosition);
soundViewController.SetPitch(PitchPosition);
soundViewController.SetVolume(SoundVolume);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
if (GUILayout.Button("Song"))
{
soundViewController.SetActiveSoundType(SoundProfileType.Song);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
if (GUILayout.Button("Sfx Sound"))
{
soundViewController.SetActiveSoundType(SoundProfileType.Sfx);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
if (GUILayout.Button("Movie Audio"))
{
soundViewController.SetActiveSoundType(SoundProfileType.MovieAudio);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
if (soundViewController.ModVoiceDictionary.Count > 0)
@@ -389,6 +395,7 @@ private void BuildSelectorManager(Single width)
if (GUILayout.Button("Mod Voices"))
{
soundViewController.SetActiveSoundType(SoundProfileType.Voice);
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
}
@@ -402,12 +409,14 @@ private void BuildSelectorManager(Single width)
if (GUILayout.Button("<"))
{
soundViewController.PreviousPlayList();
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
GUILayout.Label(soundViewController.PlaylistInfo, GUILayout.Width(width / 3f));
if (GUILayout.Button(">"))
{
soundViewController.NextPlayList();
+ searchString = "";
soundSelectorScrollPosition = Vector2.zero;
}
}
@@ -961,17 +970,52 @@ private Single BuildEffectParam(String name, Single value, Single min, Single ma
private void BuildSfxSoundSelector()
{
+ String search = GUILayout.TextField(searchString);
+ if (search != searchString)
+ {
+ searchString = search;
+ }
+
+ if (sfxSoundUIState == 1)
+ {
+ if (GUILayout.Button("Back"))
+ {
+ sfxSoundUIState = 0;
+ searchString = "";
+ }
+ }
+
soundSelectorScrollPosition = GUILayout.BeginScrollView(soundSelectorScrollPosition, GUILayout.ExpandHeight(true));
+
if (sfxSoundUIState == 0)
{
foreach (Int32 num in soundViewController.AllSfxGroupSongIndex)
{
+ String sfxName;
+ if (Enum.IsDefined(typeof(SpecialEffect), num))
+ {
+ sfxName = ((SpecialEffect)num).ToString().Replace("__", " - ").Replace("_", " ");
+ sfxName = $"{sfxName} ({num})";
+ }
+ else
+ {
+ sfxName = "EFX ID: " + num;
+ }
+
+ if (!String.IsNullOrEmpty(searchString) &&
+ !sfxName.ToLower().Contains(searchString.ToLower()) &&
+ !num.ToString().Contains(searchString))
+ {
+ continue;
+ }
+
GUILayout.BeginHorizontal();
{
- if (GUILayout.Button("Load EFX ID: " + num))
+ if (GUILayout.Button(sfxName))
{
CurrentSpecialEffectID = num;
sfxSoundUIState = 1;
+ searchString = "";
soundViewController.LoadSfxSoundGroup(num);
}
}
@@ -983,17 +1027,20 @@ private void BuildSfxSoundSelector()
List sfxSoundPlaylist = soundViewController.GetSfxSoundPlaylist(CurrentSpecialEffectID);
GUILayout.BeginVertical();
{
- if (GUILayout.Button("Back"))
- {
- sfxSoundUIState = 0;
- }
for (Int32 i = 0; i < sfxSoundPlaylist.Count; i++)
{
- if (i == SoundLib.GetResidentSfxSoundCount())
+ if (i == SoundLib.GetResidentSfxSoundCount() && String.IsNullOrEmpty(searchString))
{
GUILayout.Label("---- ---- ---- ----");
}
+
String text = sfxSoundPlaylist[i];
+
+ if (!String.IsNullOrEmpty(searchString) && !text.ToLower().Contains(searchString.ToLower()))
+ {
+ continue;
+ }
+
GUILayout.BeginHorizontal();
{
if (GUILayout.Button(text))
@@ -1015,8 +1062,7 @@ private void BuildSfxSoundSelector()
private void BuildVoiceSoundSelector()
{
- List voices = soundViewController.GetPlaylist();
- if (voices == null || voices.Count == 0)
+ if (!soundViewController.HasActiveVoiceMod)
{
soundSelectorScrollPosition = GUILayout.BeginScrollView(soundSelectorScrollPosition);
foreach (String mod in soundViewController.ModVoiceDictionary.Keys)
@@ -1026,24 +1072,28 @@ private void BuildVoiceSoundSelector()
if (GUILayout.Button(mod))
{
soundViewController.GenerateVoiceList(mod);
+ searchString = "";
}
}
GUILayout.EndHorizontal();
}
+ GUILayout.EndScrollView();
}
else
{
String search = GUILayout.TextField(searchString);
if (search != searchString)
{
- soundViewController.FilterVoiceList(search);
+ searchString = search;
+ soundViewController.FilterPlaylist(search);
}
- searchString = search;
if (GUILayout.Button("Back"))
{
soundViewController.GenerateVoiceList("");
+ searchString = "";
}
+
soundSelectorScrollPosition = GUILayout.BeginScrollView(soundSelectorScrollPosition);
List playlist = soundViewController.GetPlaylist();
if (playlist != null)
@@ -1058,12 +1108,19 @@ private void BuildVoiceSoundSelector()
GUILayout.EndHorizontal();
}
}
+ GUILayout.EndScrollView();
}
- GUILayout.EndScrollView();
}
private void BuildSoundSelector()
{
+ String search = GUILayout.TextField(searchString);
+ if (search != searchString)
+ {
+ searchString = search;
+ soundViewController.FilterPlaylist(search);
+ }
+
soundSelectorScrollPosition = GUILayout.BeginScrollView(soundSelectorScrollPosition);
List playlist = soundViewController.GetPlaylist();
if (playlist != null)
@@ -1094,7 +1151,7 @@ private void BuildPresetManager(Single width)
if (GUILayout.Button("Enable All"))
{
presetChanged = true;
- soundViewController.CurrentEffect.Effects = AudioEffectManager.EffectPreset.Effect.All;
+ soundViewController.CurrentEffect.Effects = EffectPreset.Effect.All;
soundViewController.SetReverb();
soundViewController.SetEq();
diff --git a/Assembly-CSharp/SoundDebugRoom/SoundViewController.cs b/Assembly-CSharp/SoundDebugRoom/SoundViewController.cs
index 9de672c6b..e5df6b8f5 100644
--- a/Assembly-CSharp/SoundDebugRoom/SoundViewController.cs
+++ b/Assembly-CSharp/SoundDebugRoom/SoundViewController.cs
@@ -45,6 +45,7 @@ public void SetActiveSoundType(SoundProfileType type)
return;
}
currentPlaylist = 0;
+ currentFilter = "";
PlaylistInfo = "";
PlaylistDetail = "";
filteredPlaylist = null;
@@ -411,6 +412,7 @@ private List SplitIntoNaturalParts(string input)
public void GenerateVoiceList(String modLocation)
{
currentVoiceMod = modLocation;
+ currentFilter = "";
PlaylistInfo = "";
PlaylistDetail = "";
currentPlaylist = 0;
@@ -418,21 +420,11 @@ public void GenerateVoiceList(String modLocation)
GeneratePlaylistData();
}
- public void FilterVoiceList(String filter)
+ public void FilterPlaylist(String filter)
{
- voiceFilter = filter;
+ currentFilter = filter;
currentPlaylist = 0;
-
- if (!ModVoiceDictionary.ContainsKey(currentVoiceMod))
- return;
-
- filteredPlaylist = ModVoiceDictionary[currentVoiceMod];
- if (voiceFilter.Length > 0)
- {
- filteredPlaylist = filteredPlaylist.Where((p) => p.ResourceID.ToLower().Contains(voiceFilter.ToLower())).ToList();
- }
- if (filteredPlaylist.Count == 0)
- filteredPlaylist = ModVoiceDictionary[currentVoiceMod];
+ filteredPlaylist = null;
GeneratePlaylistData();
}
@@ -491,34 +483,10 @@ public void ApplyEffectPreset(String name)
public void NextPlayList()
{
- Int32 count = 0;
- if (activeType == SoundProfileType.Music)
- {
- count = allMusicIndex.Count;
- }
- else if (activeType == SoundProfileType.SoundEffect)
- {
- count = allSoundEffectIndex.Count;
- }
- else if (activeType == SoundProfileType.Song)
- {
- count = allSongIndex.Count;
- }
- else if (activeType == SoundProfileType.Sfx)
- {
- SoundLib.LogWarning("Does not support SoundProfileType.Sfx");
- }
- else if (activeType == SoundProfileType.MovieAudio)
- {
- count = allMovieAudioIndex.Count;
- }
- else if (activeType == SoundProfileType.Voice && filteredPlaylist != null)
- {
- count = filteredPlaylist.Count;
- }
- Int32 num = (Int32)((count % 100 != 0) ? 1 : 0);
- Int32 num2 = count / 100 + num;
- if (currentPlaylist < num2 - 1)
+ if (activeType == SoundProfileType.Sfx) return;
+ Int32 count = filteredPlaylist != null ? filteredPlaylist.Count : 0;
+ Int32 maxPage = Math.Max(0, (count - 1) / 100);
+ if (currentPlaylist < maxPage)
{
currentPlaylist++;
GeneratePlaylistData();
@@ -591,96 +559,61 @@ private void GeneratePlaylistData()
private List GetActiveTypePlaylist()
{
- List list = null;
- if (activeType == SoundProfileType.Music)
- {
- list = allMusicIndex;
- }
- else if (activeType == SoundProfileType.SoundEffect)
- {
- list = allSoundEffectIndex;
- }
- else if (activeType == SoundProfileType.Song)
- {
- list = allSongIndex;
- }
- else if (activeType == SoundProfileType.Sfx)
- {
- SoundLib.LogWarning("GetPlaylist does not support SoundProfileType.Sfx");
- }
- else if (activeType == SoundProfileType.MovieAudio)
- {
- list = allMovieAudioIndex;
- }
- else if (activeType == SoundProfileType.Voice && ModVoiceDictionary.ContainsKey(currentVoiceMod))
- {
- if (filteredPlaylist == null)
- FilterVoiceList(voiceFilter);
+ if (activeType == SoundProfileType.Sfx) return null;
- Int32 index = Math.Min(currentPlaylist * 100, filteredPlaylist.Count - 1);
- Int32 count = (100 + index) > filteredPlaylist.Count ? filteredPlaylist.Count - index : 100;
- return filteredPlaylist.GetRange(index, count);
- }
- if (list == null)
- {
- return null;
- }
- if (currentPlaylist < 0)
+ if (filteredPlaylist == null)
{
- return null;
- }
- if (currentPlaylist > list.Count)
- {
- return null;
- }
- Int32 num = currentPlaylist * 100;
- List list2 = new List();
- Int32 num2 = num;
- while (num2 < num + 100 && num2 < list.Count)
- {
- list2.Add(SoundMetaData.GetSoundProfile(list[num2], activeType));
- num2++;
+ filteredPlaylist = new List();
+ if (activeType == SoundProfileType.Voice)
+ {
+ if (ModVoiceDictionary.ContainsKey(currentVoiceMod))
+ {
+ var voices = ModVoiceDictionary[currentVoiceMod];
+ if (String.IsNullOrEmpty(currentFilter))
+ filteredPlaylist.AddRange(voices);
+ else
+ filteredPlaylist.AddRange(voices.Where(p => p.ResourceID.ToLower().Contains(currentFilter.ToLower())));
+ }
+ }
+ else
+ {
+ List list = null;
+ if (activeType == SoundProfileType.Music) list = allMusicIndex;
+ else if (activeType == SoundProfileType.SoundEffect) list = allSoundEffectIndex;
+ else if (activeType == SoundProfileType.Song) list = allSongIndex;
+ else if (activeType == SoundProfileType.MovieAudio) list = allMovieAudioIndex;
+
+ if (list != null)
+ {
+ foreach (Int32 id in list)
+ {
+ SoundProfile p = SoundMetaData.GetSoundProfile(id, activeType);
+ if (String.IsNullOrEmpty(currentFilter) ||
+ (p.Name != null && p.Name.ToLower().Contains(currentFilter.ToLower())) ||
+ p.SoundIndex.ToString().Contains(currentFilter))
+ {
+ filteredPlaylist.Add(p);
+ }
+ }
+ }
+ }
}
- return list2;
+
+ if (filteredPlaylist.Count == 0) return new List();
+ Int32 index = Math.Min(currentPlaylist * 100, Math.Max(0, filteredPlaylist.Count - 1));
+ Int32 count = Math.Min(100, filteredPlaylist.Count - index);
+ return filteredPlaylist.GetRange(index, count);
}
private void SetPlaylistInfo(List allSoundProfile)
{
- Int32 count = 0;
- if (activeType == SoundProfileType.Music)
- {
- count = allMusicIndex.Count;
- }
- else if (activeType == SoundProfileType.SoundEffect)
- {
- count = allSoundEffectIndex.Count;
- }
- else if (activeType == SoundProfileType.Song)
- {
- count = allSongIndex.Count;
- }
- else if (activeType == SoundProfileType.Sfx)
- {
- SoundLib.LogWarning("SetPlaylistInfo does not support SoundProfileType.Sfx");
- }
- else if (activeType == SoundProfileType.MovieAudio)
- {
- count = allMovieAudioIndex.Count;
- }
- else if (activeType == SoundProfileType.Voice)
- {
- count = ModVoiceDictionary[currentVoiceMod].Where((p) => p.ResourceID.Contains(voiceFilter)).Count();
- }
- PlaylistInfo = currentPlaylist + 1 + "/" + (count / 100 + 1);
+ if (activeType == SoundProfileType.Sfx) return;
+
+ Int32 count = filteredPlaylist != null ? filteredPlaylist.Count : 0;
+ Int32 maxPage = Math.Max(1, (count - 1) / 100 + 1);
+ PlaylistInfo = (currentPlaylist + 1) + "/" + maxPage;
Int32 num = currentPlaylist * 100;
- PlaylistDetail = String.Concat(new Object[]
- {
- num + 1,
- "-",
- num + allSoundProfile.Count,
- " of ",
- count
- });
+ PlaylistDetail = $"{num + (count > 0 ? 1 : 0)}-{num + allSoundProfile.Count} of {count}";
}
public List GetSfxSoundPlaylist(Int32 specialEffectID)
@@ -783,8 +716,9 @@ public Boolean IsEffectVolumeEnabled
public Dictionary> ModVoiceDictionary = new Dictionary>();
private String currentVoiceMod = "";
+ public Boolean HasActiveVoiceMod => !String.IsNullOrEmpty(currentVoiceMod);
- private String voiceFilter = "";
+ public String currentFilter = "";
private SoundProfileType activeType = SoundProfileType.SoundEffect;
diff --git a/SaXAudio/AudioVoice.cpp b/SaXAudio/AudioVoice.cpp
index 7c258d266..97d0f37ef 100644
--- a/SaXAudio/AudioVoice.cpp
+++ b/SaXAudio/AudioVoice.cpp
@@ -30,9 +30,11 @@ namespace SaXAudio
if (!SourceVoice || !BankData) return false;
Log(BankID, VoiceID, "[Start] at: " + to_string(atSample) + (Looping ? " loop start: " + to_string(LoopStart) + " loop end: " + to_string(LoopEnd) : ""));
- // Update position offset
+ XAUDIO2_VOICE_STATE state;
+ SourceVoice->GetState(&state);
+
m_positionOffset = atSample;
- if (IsPlaying)
+ if (IsPlaying || state.BuffersQueued > 0)
{
if (flush)
{
@@ -40,11 +42,12 @@ namespace SaXAudio
SourceVoice->Stop();
SourceVoice->FlushSourceBuffers();
}
- XAUDIO2_VOICE_STATE state;
- SourceVoice->GetState(&state);
m_positionOffset -= state.SamplesPlayed;
}
+ Fader::Instance.StopFade(m_volumeFadeID);
+ m_volumeFadeID = 0;
+
// Set up buffer
Buffer.PlayBegin = atSample;
Buffer.PlayLength = 0; // Plays until the end