Пример #1
0
 /// <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);
Пример #2
0
 /// <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);