/// <summary> /// Compares this RBMid with another RBMid. /// /// Returns null if they are equivalent. /// If they are not equivalent, this returns the first field name in which they differ. /// For multi-dimensional fields, the return value will look like this: /// "Lyrics[0].Lyrics[0].Text" /// </summary> /// <param name="other">The RBMid to compare to</param> /// <returns>null if the files are equivalent, or else a string describing the first differing field</returns> public string Compare(RBMid other) => Check(other.Format, Format, nameof(Format)) ?? Check(other.Lyrics, Lyrics, nameof(Lyrics), (their, my) => Check(their.TrackName, my.TrackName, nameof(my.TrackName)) ?? Check(their.Lyrics, my.Lyrics, nameof(my.Lyrics), CheckTickText) ?? Check(their.Unknown1, my.Unknown1, nameof(my.Unknown1)) ?? Check(their.Unknown2, my.Unknown2, nameof(my.Unknown2)) ?? Check(their.Unknown3, my.Unknown3, nameof(my.Unknown3))) ?? Check(other.DrumFills, DrumFills, nameof(DrumFills), (their, my) => Check(their.Lanes, my.Lanes, nameof(my.Lanes), (their2, my2) => Check(their2.Tick, my2.Tick, nameof(my2.Tick)) ?? Check(their2.Lanes, my2.Lanes, nameof(my2.Lanes))) ?? Check(their.Fills, my.Fills, nameof(my.Fills), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) // TODO: Figure out why this is not always the same after conversion ?? CheckFloats(their2.EndTick, my2.EndTick, nameof(my2.EndTick), 11) ?? Check(their2.IsBRE, my2.IsBRE, nameof(my2.IsBRE)))) ?? Check(other.Anims, Anims, nameof(Anims), (their, my) => Check(their.TrackName, my.TrackName, nameof(my.TrackName)) ?? Check(their.Unknown1, my.Unknown1, nameof(my.Unknown1)) ?? Check(their.Unknown2, my.Unknown2, nameof(my.Unknown2)) // TODO: We are generating more events somehow. Probably to do with the broken chords //?? Check(their.Events, my.Events, nameof(my.Events), (their2, my2) => null) ?? Check(their.Unknown3, my.Unknown3, nameof(my.Unknown3))) ?? Check(other.ProMarkers, ProMarkers, nameof(ProMarkers), (their, my) => Check(their.Markers, my.Markers, nameof(my.Markers), (their2, my2) => Check(their2.Tick, my2.Tick, nameof(my2.Tick)) ?? Check(their2.Flags, my2.Flags, nameof(my2.Flags))) ?? Check(their.Unknown1, my.Unknown1, nameof(my.Unknown1)) ?? Check(their.Unknown2, my.Unknown2, nameof(my.Unknown2))) ?? Check(other.LaneMarkers, LaneMarkers, nameof(LaneMarkers), (their, my) => Check(their.Markers, my.Markers, nameof(my.Markers), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? Check(their2.EndTick, my2.EndTick, nameof(my2.EndTick)) ?? Check(their2.Lanes, my2.Lanes, nameof(my2.Lanes)))) ?? Check(other.TrillMarkers, TrillMarkers, nameof(TrillMarkers), (their, my) => Check(their.Trills, my.Trills, nameof(my.Trills), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? Check(their2.EndTick, my2.EndTick, nameof(my2.EndTick)) ?? Check(their2.FirstFret, my2.FirstFret, nameof(my2.FirstFret)) ?? Check(their2.SecondFret, my2.SecondFret, nameof(my2.SecondFret)))) ?? Check(other.DrumMixes, DrumMixes, nameof(DrumMixes), (their, my) => Check(their.Mixes, my.Mixes, nameof(my.Mixes), (t, m) => Check(t, m, "", CheckTickText))) ?? Check(other.GemTracks, GemTracks, nameof(GemTracks), (their, my) => Check(their.Gems, my.Gems, nameof(my.Gems), (their2, my2) => CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 0.2f) ?? Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 1.5f) // who ever cared about a couple ms ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? Check(their2.Lanes, my2.Lanes, nameof(my2.Lanes)) ?? Check(their2.IsHopo, my2.IsHopo, nameof(my2.IsHopo)) ?? Check(their2.NoTail, my2.NoTail, nameof(my2.NoTail)) ?? Check(their2.ProCymbal, my2.ProCymbal, nameof(my2.ProCymbal)) ) ?? Check(their.HopoThreshold, my.HopoThreshold, nameof(my.HopoThreshold))) ?? Check(other.OverdriveSoloSections, OverdriveSoloSections, nameof(OverdriveSoloSections), (their, my) => Check(their.Sections, my.Sections, nameof(my.Sections), (their2, my2) => Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)))) ?? Check(other.VocalTracks, VocalTracks, nameof(VocalTracks), (their, my) => Check(their.Percussion, my.Percussion, nameof(my.Percussion), Check) // TODO: Fix tacets on HARM tracks //?? Check(their.Tacets, my.Tacets, nameof(my.Tacets), (their2, my2) //=> CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 1f) //?? CheckFloats(their2.EndMillis, my2.EndMillis, nameof(my2.EndMillis), 2f) //) ?? Check(their.FakePhraseMarkers, my.FakePhraseMarkers, nameof(my.FakePhraseMarkers), (their2, my2) => CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 1f) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 1f) ?? Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? Check(their2.StartNoteIdx, my2.StartNoteIdx, nameof(my2.StartNoteIdx)) ?? Check(their2.EndNoteIdx, my2.EndNoteIdx, nameof(my2.EndNoteIdx)) ?? Check(their2.HasPitchedVox, my2.HasPitchedVox, nameof(my2.HasPitchedVox)) ?? Check(their2.HasUnpitchedVox, my2.HasUnpitchedVox, nameof(my2.HasUnpitchedVox)) //?? Check(their2.LowNote, my2.LowNote, nameof(my2.LowNote)) //?? Check(their2.HighNote, my2.HighNote, nameof(my2.HighNote)) ?? Check(their2.TugOfWarBitmask, my2.TugOfWarBitmask, nameof(my2.TugOfWarBitmask)) ?? Check(their2.PercussionSection, my2.PercussionSection, nameof(my2.PercussionSection))) ?? Check(their.Notes, my.Notes, nameof(my.Notes), (their2, my2) => // TODO: enable after fixing phrases null //Check(their2.PhraseIndex, my2.PhraseIndex, nameof(my2.PhraseIndex)) ?? Check(their2.MidiNote, my2.MidiNote, nameof(my2.MidiNote)) ?? Check(their2.MidiNote2, my2.MidiNote2, nameof(my2.MidiNote2)) ?? CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 0.4f) ?? Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 0.4f) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? Check(their2.Lyric, my2.Lyric, nameof(my2.Lyric)) ?? Check(their2.LastNoteInPhrase, my2.LastNoteInPhrase, nameof(my2.LastNoteInPhrase)) ?? Check(their2.False1, my2.False1, nameof(my2.False1)) ?? Check(their2.Unpitched, my2.Unpitched, nameof(my2.Unpitched)) ?? Check(their2.UnpitchedGenerous, my2.UnpitchedGenerous, nameof(my2.UnpitchedGenerous)) ?? Check(their2.RangeDivider, my2.RangeDivider, nameof(my2.RangeDivider)) ?? Check(their2.TugOfWarBitmask, my2.TugOfWarBitmask, nameof(my2.TugOfWarBitmask)) ?? Check(their2.Portamento, my2.Portamento, nameof(my2.Portamento)) ?? Check(their2.LyricShift, my2.LyricShift, nameof(my2.LyricShift)) ?? Check(their2.ShowLyric, my2.ShowLyric, nameof(my2.ShowLyric)) ) ?? Check(their.AuthoredPhraseMarkers, my.AuthoredPhraseMarkers, nameof(my.AuthoredPhraseMarkers), (their2, my2) => CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 1f) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 1f) ?? Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? Check(their2.StartNoteIdx, my2.StartNoteIdx, nameof(my2.StartNoteIdx)) ?? Check(their2.EndNoteIdx, my2.EndNoteIdx, nameof(my2.EndNoteIdx)) ?? Check(their2.HasPitchedVox, my2.HasPitchedVox, nameof(my2.HasPitchedVox)) ?? Check(their2.HasUnpitchedVox, my2.HasUnpitchedVox, nameof(my2.HasUnpitchedVox)) ?? Check(their2.LowNote, my2.LowNote, nameof(my2.LowNote)) ?? Check(their2.HighNote, my2.HighNote, nameof(my2.HighNote)) ?? Check(their2.TugOfWarBitmask, my2.TugOfWarBitmask, nameof(my2.TugOfWarBitmask)) ?? Check(their2.PercussionSection, my2.PercussionSection, nameof(my2.PercussionSection)))) ?? Check(other.UnknownOne, UnknownOne, nameof(UnknownOne)) ?? Check(other.UnknownNegOne, UnknownNegOne, nameof(UnknownNegOne)) ?? Check(other.UnknownHundred, UnknownHundred, nameof(UnknownHundred)) ?? Check(other.Unknown4, Unknown4, nameof(Unknown4), (their, my) // TODO: What is this? => // Check(their.Tick, my.Tick, nameof(my.Tick)) // ?? Check(their.FloatData, my.FloatData, nameof(my.FloatData)) null ) //?? Check(other.VocalRange, VocalRange, nameof(VocalRange), (their, my) // => Check(their.StartMillis, my.StartMillis, nameof(my.StartMillis)) // ?? Check(their.StartTicks, my.StartTicks, nameof(my.StartTicks)) // ?? Check(their.LowNote, my.LowNote, nameof(my.LowNote)) // ?? Check(their.HighNote, my.HighNote, nameof(my.HighNote))) ?? Check(other.HopoThreshold, HopoThreshold, nameof(HopoThreshold)) ?? Check(other.NumPlayableTracks, NumPlayableTracks, nameof(NumPlayableTracks)) ?? Check(other.FinalEventTick, FinalEventTick, nameof(FinalEventTick)) ?? Check(other.UnknownZeroByte, UnknownZeroByte, nameof(UnknownZeroByte)) ?? CheckFloats(other.PreviewStartMillis, PreviewStartMillis, nameof(PreviewStartMillis)) ?? CheckFloats(other.PreviewEndMillis, PreviewEndMillis, nameof(PreviewEndMillis)) ?? Check(other.HandMaps, HandMaps, nameof(HandMaps), (their, my) => CheckFloats(their.StartTime, my.StartTime, nameof(my.StartTime), 0.1f) ?? Check(their.Map, my.Map, nameof(my.Map))) ?? Check(other.GuitarLeftHandPos, GuitarLeftHandPos, nameof(GuitarLeftHandPos), (their, my) => CheckFloats(their.StartTime, my.StartTime, nameof(my.StartTime), 0.0002f) ?? CheckFloats(their.Length, my.Length, nameof(my.Length), 0.2f) ?? Check(their.Position, my.Position, nameof(my.Position)) //?? Check(their.Unknown, my.Unknown, nameof(my.Unknown)) ) ?? Check(other.StrumMaps, StrumMaps, nameof(StrumMaps), (their, my) => CheckFloats(their.StartTime, my.StartTime, nameof(my.StartTime)) ?? Check(their.Map, my.Map, nameof(my.Map))) ?? Check(other.MarkupSoloNotes1, MarkupSoloNotes1, nameof(MarkupSoloNotes1), CheckSoloNotes) ?? Check(other.MarkupLoop1, MarkupLoop1, nameof(MarkupLoop1), CheckTwoTick) ?? Check(other.MarkupChords1, MarkupChords1, nameof(MarkupChords1), (their, my) => Check(their.StartTick, my.StartTick, nameof(my.StartTick)) ?? Check(their.EndTick, my.EndTick, nameof(my.EndTick)) ?? Check(their.Pitches, my.Pitches, nameof(my.Pitches), Check)) ?? Check(other.MarkupSoloNotes2, MarkupSoloNotes2, nameof(MarkupSoloNotes2), CheckSoloNotes) ?? Check(other.MarkupSoloNotes3, MarkupSoloNotes3, nameof(MarkupSoloNotes3), CheckSoloNotes) ?? Check(other.MarkupLoop2, MarkupLoop2, nameof(MarkupLoop2), CheckTwoTick) ?? Check(other.MidiSongResourceMagic, MidiSongResourceMagic, nameof(MidiSongResourceMagic)) ?? Check(other.LastTrackFinalTick, LastTrackFinalTick, nameof(LastTrackFinalTick)) ?? Check(other.MidiTracks, MidiTracks, nameof(MidiTracks), (their, my) => Check(their.Name, my.Name, nameof(my.Name)) ?? Check(their.TotalTicks, my.TotalTicks, nameof(my.TotalTicks)) ?? Check(their.Messages, my.Messages, nameof(my.Messages), (IMidiMessage their2, IMidiMessage my2) => Check(their2.DeltaTime, my2.DeltaTime, nameof(my2.DeltaTime)) ?? Check(their2.PrettyString, my2.PrettyString, "<pretty_string>"))) ?? Check(other.FinalTick, FinalTick, nameof(FinalTick)) //?? Check(other.Measures, Measures, nameof(Measures)) ?? Check(other.Unknown, Unknown, nameof(Unknown), Check) ?? Check(other.FinalTickMinusOne, FinalTickMinusOne, nameof(FinalTickMinusOne)) // TODO: Floats are sometimes 0xABCDABCD ??? //?? Check(other.UnknownFloats, UnknownFloats, nameof(UnknownFloats), Check) ?? Check(other.Tempos, Tempos, nameof(Tempos), (their, my) => CheckFloats(their.StartMillis, my.StartMillis, nameof(my.StartMillis), 0.3f) ?? Check(their.StartTick, my.StartTick, nameof(my.StartTick)) // TODO: Fix precision of tempo conversions... ?? CheckFloats(their.Tempo, my.Tempo, nameof(my.Tempo), 2)) ?? Check(other.TimeSigs, TimeSigs, nameof(TimeSigs), (their, my) => Check(their.Tick, my.Tick, nameof(my.Tick)) ?? Check(their.Measure, my.Measure, nameof(my.Measure)) ?? Check(their.Numerator, my.Numerator, nameof(my.Numerator)) ?? Check(their.Denominator, my.Denominator, nameof(my.Denominator))) ?? Check(other.Beats, Beats, nameof(Beats), (their, my) => Check(their.Tick, my.Tick, nameof(my.Tick)) ?? Check(their.Downbeat, my.Downbeat, nameof(my.Downbeat))) ?? Check(other.UnknownZero, UnknownZero, nameof(UnknownZero)) ?? Check(other.MidiTrackNames, MidiTrackNames, nameof(MidiTrackNames), Check);
/// <summary> /// Compares this RBMid with another RBMid. /// /// Returns null if they are equivalent. /// If they are not equivalent, this returns the first field name in which they differ. /// For multi-dimensional fields, the return value will look like this: /// "Lyrics[0].Lyrics[0].Text" /// </summary> /// <param name="other">The RBMid to compare to</param> /// <returns>null if the files are equivalent, or else a string describing the first differing field</returns> public string Compare(RBMid other) => Check(other.Format, Format, nameof(Format)) ?? Check(other.Lyrics, Lyrics, nameof(Lyrics), (their, my) => Check(their.TrackName, my.TrackName, nameof(my.TrackName)) ?? Check(their.Lyrics, my.Lyrics, nameof(my.Lyrics), CheckTickText) ?? Check(their.Unknown1, my.Unknown1, nameof(my.Unknown1)) ?? Check(their.Unknown2, my.Unknown2, nameof(my.Unknown2)) ?? Check(their.Unknown3, my.Unknown3, nameof(my.Unknown3))) ?? Check(other.DrumFills, DrumFills, nameof(DrumFills), (their, my) => Check(their.Lanes, my.Lanes, nameof(my.Lanes), (their2, my2) => Check(their2.Tick, my2.Tick, nameof(my2.Tick)) ?? Check(their2.Lanes, my2.Lanes, nameof(my2.Lanes))) ?? Check(their.Fills, my.Fills, nameof(my.Fills), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) // TODO: Figure out why this is not always the same after conversion ?? CheckFloats(their2.EndTick, my2.EndTick, nameof(my2.EndTick), 11) ?? Check(their2.IsBRE, my2.IsBRE, nameof(my2.IsBRE)))) // TODO: Keyboard anims... maybe ?? Check(other.Anims, Anims, nameof(Anims), (their, my) => null) ?? Check(other.ProMarkers, ProMarkers, nameof(ProMarkers), (their, my) => Check(their.Markers, my.Markers, nameof(my.Markers), (their2, my2) => Check(their2.Tick, my2.Tick, nameof(my2.Tick)) ?? Check(their2.Flags, my2.Flags, nameof(my2.Flags))) ?? Check(their.Unknown1, my.Unknown1, nameof(my.Unknown1)) ?? Check(their.Unknown2, my.Unknown2, nameof(my.Unknown2))) ?? Check(other.LaneMarkers, LaneMarkers, nameof(LaneMarkers), (their, my) => Check(their.Markers, my.Markers, nameof(my.Markers), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? Check(their2.EndTick, my2.EndTick, nameof(my2.EndTick)) ?? Check(their2.Flags, my2.Flags, nameof(my2.Flags)))) ?? Check(other.TrillMarkers, TrillMarkers, nameof(TrillMarkers), (their, my) => Check(their.Trills, my.Trills, nameof(my.Trills), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? Check(their2.EndTick, my2.EndTick, nameof(my2.EndTick)) ?? Check(their2.LowFret, my2.LowFret, nameof(my2.LowFret)) ?? Check(their2.HighFret, my2.HighFret, nameof(my2.HighFret)))) ?? Check(other.DrumMixes, DrumMixes, nameof(DrumMixes), (their, my) => Check(their.Mixes, my.Mixes, nameof(my.Mixes), (t, m) => Check(t, m, "", CheckTickText))) ?? Check(other.GemTracks, GemTracks, nameof(GemTracks), (their, my) => Check(their.Gems, my.Gems, nameof(my.Gems), (their2, my2) => CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 0.2f) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 1.5f) // who ever cared about a couple ms ?? Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? Check(their2.Lanes, my2.Lanes, nameof(my2.Lanes)) // TODO: Swing notes... //?? Check(their2.IsHopo, my2.IsHopo, nameof(my2.IsHopo)) ?? Check(their2.NoTail, my2.NoTail, nameof(my2.NoTail)) // TODO //?? Check(their2.Unknown, my2.Unknown, nameof(my2.Unknown)) )) ?? Check(other.OverdriveSoloSections, OverdriveSoloSections, nameof(OverdriveSoloSections), (their, my) => Check(their.Sections, my.Sections, nameof(my.Sections), (their2, my2) => Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)))) ?? Check(other.VocalTracks, VocalTracks, nameof(VocalTracks), (their, my) => Check(their.Notes, my.Notes, nameof(my.Notes), (their2, my2) => Check(their2.StartTick, my2.StartTick, nameof(my2.StartTick)) ?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) ?? CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 0.4f) ?? CheckFloats(their2.LengthMillis, my2.LengthMillis, nameof(my2.LengthMillis), 0.4f) ?? Check(their2.MidiNote, my2.MidiNote, nameof(my2.MidiNote)) ?? Check(their2.MidiNote2, my2.MidiNote2, nameof(my2.MidiNote2)) ?? Check(their2.PhraseIndex, my2.PhraseIndex, nameof(my2.PhraseIndex)) ?? Check(their2.Lyric, my2.Lyric, nameof(my2.Lyric)) ?? Check(their2.Portamento, my2.Portamento, nameof(my2.Portamento)) ?? Check(their2.LastNoteInPhrase, my2.LastNoteInPhrase, nameof(my2.LastNoteInPhrase))) ?? Check(their.Percussion, my.Percussion, nameof(my.Percussion), Check) ?? Check(their.Tacets, my.Tacets, nameof(my.Tacets), (their2, my2) => CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 0.2f) // TODO: Fix tacets on HARM tracks //?? CheckFloats(their2.EndMillis, my2.EndMillis, nameof(my2.EndMillis), 2f) ) ?? Check(their.PhraseMarkers, my.PhraseMarkers, nameof(my.PhraseMarkers), (their2, my2) => // TODO: Fix first phrase marker. It seems to start earlier than authored!? // CheckFloats(their2.StartMillis, my2.StartMillis, nameof(my2.StartMillis), 1f) //?? CheckFloats(their2.Length, my2.Length, nameof(my2.Length), 1f) //?? Check(their2.StartTicks, my2.StartTicks, nameof(my2.StartTicks)) //?? Check(their2.LengthTicks, my2.LengthTicks, nameof(my2.LengthTicks)) // TODO ??? //?? Check(their2.IsPhrase, my2.IsPhrase, nameof(my2.IsPhrase)) //?? Check(their2.IsOverdrive, my2.IsOverdrive, nameof(my2.IsOverdrive)) null ) ?? Check(their.PhraseMarkers2, my.PhraseMarkers2, nameof(my.PhraseMarkers2), (their2, my2) => null)) ?? Check(other.UnknownOne, UnknownOne, nameof(UnknownOne)) ?? Check(other.UnknownNegOne, UnknownNegOne, nameof(UnknownNegOne)) ?? Check(other.UnknownHundred, UnknownHundred, nameof(UnknownHundred)) ?? Check(other.Unknown4, Unknown4, nameof(Unknown4), (their, my) => null) ?? Check(other.VocalRange, VocalRange, nameof(VocalRange), (their, my) // TODO: Which one is ticks and which one is time? => Check(their.StartMillis, my.StartMillis, nameof(my.StartMillis)) ?? Check(their.StartTicks, my.StartTicks, nameof(my.StartTicks)) ?? Check(their.LowNote, my.LowNote, nameof(my.LowNote)) ?? Check(their.HighNote, my.HighNote, nameof(my.HighNote))) ?? Check(other.Unknown6, Unknown6, nameof(Unknown6)) ?? Check(other.NumPlayableTracks, NumPlayableTracks, nameof(NumPlayableTracks)) ?? Check(other.FinalEventTick, FinalEventTick, nameof(FinalEventTick)) ?? Check(other.UnknownZeroByte, UnknownZeroByte, nameof(UnknownZeroByte)) ?? CheckFloats(other.PreviewStartMillis, PreviewStartMillis, nameof(PreviewStartMillis)) ?? CheckFloats(other.PreviewEndMillis, PreviewEndMillis, nameof(PreviewEndMillis)) ?? Check(other.HandMaps, HandMaps, nameof(HandMaps), (their, my) => Check(their.StartTime, my.StartTime, nameof(my.StartTime)) ?? Check(their.Map, my.Map, nameof(my.Map))) ?? Check(other.GuitarLeftHandPos, GuitarLeftHandPos, nameof(GuitarLeftHandPos), (their, my) => CheckFloats(their.StartTime, my.StartTime, nameof(my.StartTime), 0.0002f) ?? CheckFloats(their.Length, my.Length, nameof(my.Length), 0.2f) ?? Check(their.Position, my.Position, nameof(my.Position)) ?? Check(their.Unknown, my.Unknown, nameof(my.Unknown))) ?? Check(other.StrumMaps, StrumMaps, nameof(StrumMaps), (their, my) => CheckFloats(their.StartTime, my.StartTime, nameof(my.StartTime)) ?? Check(their.Map, my.Map, nameof(my.Map))) ?? Check(other.MarkupSoloNotes1, MarkupSoloNotes1, nameof(MarkupSoloNotes1), CheckSoloNotes) ?? Check(other.MarkupLoop1, MarkupLoop1, nameof(MarkupLoop1), CheckTwoTick) ?? Check(other.MarkupChords1, MarkupChords1, nameof(MarkupChords1), (their, my) => Check(their.StartTick, my.StartTick, nameof(my.StartTick)) ?? Check(their.EndTick, my.EndTick, nameof(my.EndTick)) ?? Check(their.Pitches, my.Pitches, nameof(my.Pitches), Check)) ?? Check(other.MarkupSoloNotes2, MarkupSoloNotes2, nameof(MarkupSoloNotes2), CheckSoloNotes) ?? Check(other.MarkupSoloNotes3, MarkupSoloNotes3, nameof(MarkupSoloNotes3), CheckSoloNotes) ?? Check(other.MarkupLoop2, MarkupLoop2, nameof(MarkupLoop2), CheckTwoTick) ?? Check(other.UnknownTwo, UnknownTwo, nameof(UnknownTwo)) ?? Check(other.LastMarkupEventTick, LastMarkupEventTick, nameof(LastMarkupEventTick)) ?? Check(other.MidiTracks, MidiTracks, nameof(MidiTracks), (their, my) => Check(their.Name, my.Name, nameof(my.Name)) ?? Check(their.TotalTicks, my.TotalTicks, nameof(my.TotalTicks)) ?? Check(their.Messages, my.Messages, nameof(my.Messages), (IMidiMessage their2, IMidiMessage my2) => Check(their2.DeltaTime, my2.DeltaTime, nameof(my2.DeltaTime)) ?? Check(their2.PrettyString, my2.PrettyString, "<pretty_string>"))) ?? Check(other.FinalTick, FinalTick, nameof(FinalTick)) ?? Check(other.Measures, Measures, nameof(Measures)) ?? Check(other.Unknown, Unknown, nameof(Unknown), Check) ?? Check(other.FinalTickMinusOne, FinalTickMinusOne, nameof(FinalTickMinusOne)) // TODO: Floats are sometimes 0xABCDABCD ??? //?? Check(other.UnknownFloats, UnknownFloats, nameof(UnknownFloats), Check) ?? Check(other.Tempos, Tempos, nameof(Tempos), (their, my) => CheckFloats(their.StartMillis, my.StartMillis, nameof(my.StartMillis), 0.3f) ?? Check(their.StartTick, my.StartTick, nameof(my.StartTick)) // TODO: Fix precision of tempo conversions... ?? CheckFloats(their.Tempo, my.Tempo, nameof(my.Tempo), 2)) ?? Check(other.TimeSigs, TimeSigs, nameof(TimeSigs), (their, my) => Check(their.Tick, my.Tick, nameof(my.Tick)) ?? Check(their.Measure, my.Measure, nameof(my.Measure)) ?? Check(their.Numerator, my.Numerator, nameof(my.Numerator)) ?? Check(their.Denominator, my.Denominator, nameof(my.Denominator))) ?? Check(other.Beats, Beats, nameof(Beats), (their, my) => Check(their.Tick, my.Tick, nameof(my.Tick)) ?? Check(their.Downbeat, my.Downbeat, nameof(my.Downbeat))) ?? Check(other.UnknownZero, UnknownZero, nameof(UnknownZero)) ?? Check(other.MidiTrackNames, MidiTrackNames, nameof(MidiTrackNames), Check);