private Tuple<int, SongChordTemplate> GetChordTemplate(Chord zChord, Dictionary<string, Tuple<int, SongChordTemplate>> chordTemps)
 {
     Tuple<int, SongChordTemplate> val;
     if (!chordTemps.TryGetValue(HashChord(zChord), out val))
     {
         SongChordTemplate templ = new SongChordTemplate() { ChordName = "" };
         val = new Tuple<int, SongChordTemplate>(chordTemps.Count == 0 ? 0 : chordTemps.Values.Select(v => v.Item1).Max() + 1, templ);
         templ.Finger0 = templ.Finger1 = templ.Finger2 = templ.Finger3 = templ.Finger4 = templ.Finger5 = -1;
         templ.Fret0 = templ.Fret1 = templ.Fret2 = templ.Fret3 = templ.Fret4 = templ.Fret5 = -1;
         zChord.Notes.Where(n => n.StringNo == 0).ToList().ForEach(note => templ.Fret0 = (sbyte)note.Fret);
         zChord.Notes.Where(n => n.StringNo == 1).ToList().ForEach(note => templ.Fret1 = (sbyte)note.Fret);
         zChord.Notes.Where(n => n.StringNo == 2).ToList().ForEach(note => templ.Fret2 = (sbyte)note.Fret);
         zChord.Notes.Where(n => n.StringNo == 3).ToList().ForEach(note => templ.Fret3 = (sbyte)note.Fret);
         zChord.Notes.Where(n => n.StringNo == 4).ToList().ForEach(note => templ.Fret4 = (sbyte)note.Fret);
         zChord.Notes.Where(n => n.StringNo == 5).ToList().ForEach(note => templ.Fret5 = (sbyte)note.Fret);
         chordTemps[HashChord(zChord)] = val;
     }
     return val;
 }
        // COMPLETE
        private static void WriteRocksmithSngChordTemplates(EndianBinaryWriter w, SongChordTemplate[] chordTemplates, InstrumentTuning tuning, ArrangementType arrangementType)
        {
            // output header
            if (chordTemplates == null || chordTemplates.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }

            // output header count
            w.Write(chordTemplates.Length);

            // output chord templates
            foreach (SongChordTemplate chordTemplate in chordTemplates)
            {
                // fret numbers
                w.Write(chordTemplate.Fret0);
                w.Write(chordTemplate.Fret1);
                w.Write(chordTemplate.Fret2);
                w.Write(chordTemplate.Fret3);
                w.Write(chordTemplate.Fret4);
                w.Write(chordTemplate.Fret5);

                // finger positions
                w.Write(chordTemplate.Finger0);
                w.Write(chordTemplate.Finger1);
                w.Write(chordTemplate.Finger2);
                w.Write(chordTemplate.Finger3);
                w.Write(chordTemplate.Finger4);
                w.Write(chordTemplate.Finger5);

                // note values
                w.Write(tuning.GetMidiNote(arrangementType, 0, chordTemplate.Fret0));
                w.Write(tuning.GetMidiNote(arrangementType, 1, chordTemplate.Fret1));
                w.Write(tuning.GetMidiNote(arrangementType, 2, chordTemplate.Fret2));
                w.Write(tuning.GetMidiNote(arrangementType, 3, chordTemplate.Fret3));
                w.Write(tuning.GetMidiNote(arrangementType, 4, chordTemplate.Fret4));
                w.Write(tuning.GetMidiNote(arrangementType, 5, chordTemplate.Fret5));

                // chord name
                string name = chordTemplate.ChordName;
                if (name.Length > 32)
                {
                    name = name.Substring(0, 32);
                }
                foreach (char c in name)
                {
                    w.Write(Convert.ToByte(c));
                }
                // padding after name
                w.Write(new byte[32 - name.Length]);
            }
        }