diff --git a/WwiseParserLib/Parsers/HIRCParser.cs b/WwiseParserLib/Parsers/HIRCParser.cs
index ee6a97d..50dd8e0 100644
--- a/WwiseParserLib/Parsers/HIRCParser.cs
+++ b/WwiseParserLib/Parsers/HIRCParser.cs
@@ -205,28 +205,16 @@ public static SoundBankHierarchyChunk Parse2019(byte[] blob, bool noParse = fals
}
else
{
- switch ((HIRCObjectType)objectType)
+ hircObject = (HIRCObjectType) objectType switch
{
- case HIRCObjectType.MusicSegment:
- hircObject = ParseMusicSegment2019(objectBlob);
- break;
-
- case HIRCObjectType.MusicTrack:
- hircObject = ParseMusicTrack2019(objectBlob);
- break;
-
- case HIRCObjectType.MusicSwitchContainer:
- hircObject = ParseMusicSwitchContainer2019(objectBlob);
- break;
-
- case HIRCObjectType.MusicPlaylistContainer:
- hircObject = ParseMusicPlaylistContainer2019(objectBlob);
- break;
-
- default:
- hircObject = ParseUnknown(objectType, objectBlob);
- break;
- }
+ HIRCObjectType.Event => ParseEvent2019(objectBlob),
+ HIRCObjectType.EventAction => ParseEventAction(objectBlob),
+ HIRCObjectType.MusicSegment => ParseMusicSegment2019(objectBlob),
+ HIRCObjectType.MusicTrack => ParseMusicTrack2019(objectBlob),
+ HIRCObjectType.MusicSwitchContainer => ParseMusicSwitchContainer2019(objectBlob),
+ HIRCObjectType.MusicPlaylistContainer => ParseMusicPlaylistContainer2019(objectBlob),
+ _ => ParseUnknown(objectType, objectBlob)
+ };
}
hircSection.Objects[i] = hircObject;
@@ -748,10 +736,18 @@ public static MusicSwitchContainer ParseMusicSwitchContainer2013(byte[] data)
for (var i = 0; i < musicSwitchContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -840,10 +836,18 @@ public static MusicSwitchContainer ParseMusicSwitchContainer(byte[] data)
for (var i = 0; i < musicSwitchContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -932,10 +936,18 @@ public static MusicSwitchContainer ParseMusicSwitchContainer2019(byte[] data)
for (var i = 0; i < musicSwitchContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -1219,18 +1231,18 @@ public static MusicTrack ParseMusicTrack2019(byte[] data)
MusicTrackTimeParameter timeParameter = default;
timeParameter.SubTrackIndex = reader.ReadUInt32();
timeParameter.AudioId = reader.ReadUInt32();
- reader.BaseStream.Position += 4; // Unknown uint or float
+ timeParameter.EventId = reader.ReadUInt32();
timeParameter.BeginOffset = reader.ReadDouble();
timeParameter.BeginTrimOffset = reader.ReadDouble();
timeParameter.EndTrimOffset = reader.ReadDouble();
timeParameter.EndOffset = reader.ReadDouble();
musicTrack.TimeParameters[i] = timeParameter;
}
- musicTrack.SubTrackCount = reader.ReadUInt32();
- if (musicTrack.SoundCount > 0)
+ if (musicTrack.TimeParameterCount > 0)
{
- musicTrack.CurveCount = reader.ReadUInt32();
+ musicTrack.SubTrackCount = reader.ReadUInt32();
}
+ musicTrack.CurveCount = reader.ReadUInt32();
musicTrack.Curves = new MusicTrackCurve[musicTrack.CurveCount];
for (var i = 0; i < musicTrack.CurveCount; i++)
{
@@ -1298,6 +1310,24 @@ public static Event ParseEvent(byte[] data)
}
}
+ public static Event ParseEvent2019(byte[] data)
+ {
+ using (var reader = new BinaryReader(new MemoryStream(data)))
+ {
+ var @event = new Event(data.Length);
+ @event.Id = reader.ReadUInt32();
+ @event.ActionCount = reader.ReadByte();
+ @event.ActionIds = new uint[@event.ActionCount];
+ for (var i = 0; i < @event.ActionCount; i++)
+ {
+ @event.ActionIds[i] = reader.ReadUInt32();
+ }
+
+ Debug.Assert(reader.BaseStream.Position == reader.BaseStream.Length);
+ return @event;
+ }
+ }
+
public static EventAction ParseEventAction(byte[] data)
{
using (var reader = new BinaryReader(new MemoryStream(data)))
@@ -1314,28 +1344,71 @@ public static EventAction ParseEventAction(byte[] data)
{
eventAction.ParameterTypes[i] = (AudioParameterType)reader.ReadByte();
}
- eventAction.ParameterValues = new float[eventAction.ParameterCount];
+ eventAction.ParameterValues = new int[eventAction.ParameterCount];
for (var i = 0; i < eventAction.ParameterCount; i++)
{
- eventAction.ParameterValues[i] = reader.ReadSingle();
+ eventAction.ParameterValues[i] = reader.ReadInt32();
+ }
+ eventAction.ParameterPairCount = reader.ReadByte();
+ eventAction.ParameterPairTypes = new byte[eventAction.ParameterPairCount];
+ for (var i = 0; i < eventAction.ParameterPairCount; i++)
+ {
+ eventAction.ParameterPairTypes[i] = reader.ReadByte();
}
- eventAction.Unknown_08 = reader.ReadByte();
- EventActionSettings settings;
- switch (eventAction.ActionType)
+ eventAction.ParameterPairValues = new AudioParameterPair[eventAction.ParameterPairCount];
+ for (var i = 0; i < eventAction.ParameterPairCount; i++)
{
- case EventActionType.Play:
- settings = new EventActionPlaySettings();
- ((EventActionPlaySettings)settings).FadeInCurve = (AudioCurveShapeByte)reader.ReadByte();
- ((EventActionPlaySettings)settings).ObjectSoundBankId = reader.ReadUInt32();
- break;
+ AudioParameterPair audioParameterPair = default;
+ audioParameterPair.Parameter_1 = reader.ReadSingle();
+ audioParameterPair.Parameter_2 = reader.ReadSingle();
+ eventAction.ParameterPairValues[i] = audioParameterPair;
+ }
+
- default:
- settings = new EventActionUnknownSettings();
- ((EventActionUnknownSettings)settings).Blob
- = reader.ReadBytes(data.Length - (int)reader.BaseStream.Position);
- break;
+ // Read custom settings
+ if (eventAction.ActionType.HasSettings())
+ {
+ EventActionSettings settings = null;
+ switch (eventAction.ActionType)
+ {
+ case EventActionType.Stop:
+ var stop = new EventActionStopSettings();
+ stop.FadeOutCurve = (AudioCurveShapeByte) reader.ReadByte();
+ stop.Flag = reader.ReadByte();
+ reader.ReadEventActionExceptions(stop);
+ settings = stop;
+ break;
+ case EventActionType.Pause:
+ var pause = new EventActionPauseSettings();
+ pause.FadeOutCurve = (AudioCurveShapeByte) reader.ReadByte();
+ reader.ReadEventActionExceptions(pause);
+ settings = pause;
+ break;
+ case EventActionType.Resume:
+ var resume = new EventActionResumeSettings();
+ resume.FadeInCurve = (AudioCurveShapeByte) reader.ReadByte();
+ resume.Flag = reader.ReadByte();
+ reader.ReadEventActionExceptions(resume);
+ settings = resume;
+ break;
+ case EventActionType.Play:
+ var play = new EventActionPlaySettings();
+ play.FadeInCurve = (AudioCurveShapeByte) reader.ReadByte();
+ play.TargetSoundBankId = reader.ReadUInt32();
+ settings = play;
+ break;
+ case EventActionType.Seek:
+ var seek = new EventActionSeekSettings();
+ seek.SeekType = (EventActionSeekType) reader.ReadByte();
+ seek.Seek = reader.ReadSingle();
+ seek.Unknown_0 = reader.ReadUInt32();
+ seek.Unknown_1 = reader.ReadUInt32();
+ seek.SeekToNearestMarker = reader.ReadBoolean();
+ settings = seek;
+ break;
+ }
+ eventAction.Settings = settings;
}
- eventAction.Settings = settings;
// FIXME: we don't fully understand Play EventAction, will trip the assert
//Debug.Assert(reader.BaseStream.Position == reader.BaseStream.Length);
@@ -1416,10 +1489,18 @@ public static MusicPlaylistContainer ParseMusicPlaylistContainer2013(byte[] data
for (var i = 0; i < musicPlaylistContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -1495,10 +1576,18 @@ public static MusicPlaylistContainer ParseMusicPlaylistContainer(byte[] data)
for (var i = 0; i < musicPlaylistContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -1574,10 +1663,18 @@ public static MusicPlaylistContainer ParseMusicPlaylistContainer2019(byte[] data
for (var i = 0; i < musicPlaylistContainer.TransitionCount; i++)
{
MusicTransition transition = default;
- transition.Unknown_1 = reader.ReadUInt32();
- transition.SourceId = reader.ReadUInt32();
- transition.Unknown_2 = reader.ReadUInt32();
- transition.DestinationId = reader.ReadUInt32();
+ transition.SourceIdCount = reader.ReadUInt32();
+ transition.SourceIds = new uint[transition.SourceIdCount];
+ for (var j = 0; j < transition.SourceIdCount; j++)
+ {
+ transition.SourceIds[j] = reader.ReadUInt32();
+ }
+ transition.DestinationIdCount = reader.ReadUInt32();
+ transition.DestinationIds = new uint[transition.DestinationIdCount];
+ for (var j = 0; j < transition.DestinationIdCount; j++)
+ {
+ transition.DestinationIds[j] = reader.ReadUInt32();
+ }
transition.FadeOutDuration = reader.ReadUInt32();
transition.FadeOutCurveShape = (AudioCurveShapeUInt)reader.ReadUInt32();
transition.FadeOutOffset = reader.ReadInt32();
@@ -2330,5 +2427,19 @@ private static MusicPlaylistElement ReadPlaylistElement(this BinaryReader reader
return musicPlaylistElement;
}
+
+ private static void ReadEventActionExceptions(
+ this BinaryReader reader, EventActionSettingsWithExceptions settings)
+ {
+ settings.ExceptionCount = reader.ReadByte();
+ settings.Exceptions = new EventActionException[settings.ExceptionCount];
+ for (var i = 0; i < settings.ExceptionCount; i++)
+ {
+ EventActionException exception = new EventActionException();
+ exception.Id = reader.ReadUInt32();
+ exception.Unknown = reader.ReadByte();
+ settings.Exceptions[i] = exception;
+ }
+ }
}
}
diff --git a/WwiseParserLib/Structures/Objects/HIRC/EventAction.cs b/WwiseParserLib/Structures/Objects/HIRC/EventAction.cs
index 63657be..77cb31b 100644
--- a/WwiseParserLib/Structures/Objects/HIRC/EventAction.cs
+++ b/WwiseParserLib/Structures/Objects/HIRC/EventAction.cs
@@ -16,13 +16,19 @@ public EventAction(int length) : base(HIRCObjectType.EventAction, (uint)length)
public uint ObjectId { get; set; }
- public byte Unknown_06 { get; set; } // 0
+ public byte Unknown_06 { get; set; } // 0, 1 appears in D2BL
public byte ParameterCount { get; set; }
public AudioParameterType[] ParameterTypes { get; set; }
- public float[] ParameterValues { get; set; }
+ public int[] ParameterValues { get; set; }
+
+ public byte ParameterPairCount { get; set; }
+
+ public byte[] ParameterPairTypes { get; set; }
+
+ public AudioParameterPair[] ParameterPairValues { get; set; }
public EventActionSettings Settings { get; set; }
}
diff --git a/WwiseParserLib/Structures/Objects/HIRC/MusicSwitchContainer.cs b/WwiseParserLib/Structures/Objects/HIRC/MusicSwitchContainer.cs
index f8eac2f..d47626a 100644
--- a/WwiseParserLib/Structures/Objects/HIRC/MusicSwitchContainer.cs
+++ b/WwiseParserLib/Structures/Objects/HIRC/MusicSwitchContainer.cs
@@ -101,26 +101,26 @@ public MusicSwitchContainer(int length) : base(HIRCObjectType.MusicSwitchContain
public struct MusicTransition
{
///
- /// Unknown value. Appears to always be 1.
+ /// Number of transition source IDs.
///
- public uint Unknown_1 { get; set; }
+ public uint SourceIdCount { get; set; }
///
/// The ID of the transition source object.
/// Location: Music Switch Container Property Editor > Transitions > Source
///
- public uint SourceId { get; set; }
+ public uint[] SourceIds { get; set; }
///
- /// Unknown value. Appears to always be 1.
+ /// Number of transition destination IDs.
///
- public uint Unknown_2 { get; set; }
+ public uint DestinationIdCount { get; set; }
///
/// The ID of the transition destination object.
/// Location: Music Switch Container Property Editor > Transitions > Destination
///
- public uint DestinationId { get; set; }
+ public uint[] DestinationIds { get; set; }
///
/// The duration of source fade-out, in milliseconds.
diff --git a/WwiseParserLib/Structures/Objects/HIRC/MusicTrack.cs b/WwiseParserLib/Structures/Objects/HIRC/MusicTrack.cs
index d462090..7c2231e 100644
--- a/WwiseParserLib/Structures/Objects/HIRC/MusicTrack.cs
+++ b/WwiseParserLib/Structures/Objects/HIRC/MusicTrack.cs
@@ -128,6 +128,11 @@ public struct MusicTrackTimeParameter
///
public uint AudioId { get; set; }
+ ///
+ /// The corresponding event ID.
+ ///
+ public uint EventId { get; set; }
+
///
/// The start offset of this Music Track, relative to the timeline of its parent.
///