private static string HashChord(ZpeChord chord)
        {
            string hash = "";

            chord.Notes.OrderBy(n => n.StringNo).ToList().ForEach(ch => hash += ch.StringNo + "." + ch.Fret + ".");
            return(hash);
        }
        private SongNote GetNote(ZpeChord chord, ZpeChord nextChord)
        {
            SongNote note  = new SongNote();
            ZpeNote  zNote = chord.Notes[0];

            note.Fret     = (sbyte)zNote.Fret;
            note.String   = (byte)zNote.StringNo;
            note.Bend     = 0;
            note.HammerOn = (zNote.IsTapNote || chord.IsHammerOn) ? (byte)1 : (byte)0;
            note.Harmonic = 0;
            note.Hopo     = note.HammerOn;
            note.Ignore   = 0;
            note.PalmMute = (zNote.IsXNote || chord.IsMute) ? (byte)1 : (byte)0;
            note.Sustain  = (chord.EndTime - chord.StartTime > .5) ? chord.EndTime - chord.StartTime : 0;
            note.Time     = (float)chord.StartTime;
            note.Tremolo  = 0;
            if (chord.IsSlide && nextChord != null)
            {
                note.SlideTo  = (sbyte)Math.Max(nextChord.Notes[0].Fret, 1);
                note.Sustain  = chord.EndTime - chord.StartTime;
                note.HammerOn = note.Hopo = note.PalmMute = 0;
            }
            else
            {
                note.SlideTo = -1;
            }
            return(note);
        }
        private static SongNote2014 GetNote(ZpeChord chord, ZpeChord nextChord, int zNoteIndex = 0)
        {
            SongNote2014 note  = new SongNote2014();
            ZpeNote      zNote = chord.Notes[zNoteIndex];

            note.Fret           = (sbyte)zNote.Fret;
            note.String         = (byte)zNote.StringNo;
            note.Time           = (float)chord.StartTime;
            note.Accent         = 0;
            note.Bend           = 0;
            note.HammerOn       = (zNote.IsTapNote || chord.IsHammerOn) ? (byte)1 : (byte)0;
            note.Harmonic       = 0;
            note.HarmonicPinch  = 0;
            note.Hopo           = note.HammerOn;
            note.Ignore         = 0;
            note.LinkNext       = 0;
            note.LeftHand       = -1;
            note.Mute           = 0;
            note.PalmMute       = (zNote.IsXNote || chord.IsMute) ? (byte)1 : (byte)0;
            note.Pluck          = -1;
            note.PullOff        = 0;
            note.RightHand      = -1;
            note.Slap           = -1;
            note.SlideUnpitchTo = -1;
            note.Sustain        = (chord.EndTime - chord.StartTime > .5) ? chord.EndTime - chord.StartTime : 0;
            note.Tap            = 0;
            note.Tremolo        = 0;
            note.Vibrato        = 0;

            if (chord.IsSlide && nextChord != null)
            {
                note.SlideTo  = (sbyte)Math.Max(nextChord.Notes[0].Fret, 1);
                note.Sustain  = chord.EndTime - chord.StartTime;
                note.HammerOn = note.Hopo = note.PalmMute = 0;
            }
            else
            {
                note.SlideTo = -1;
            }

            //// no advanced techniques for now
            //note.SlideTo = -1;
            //note.Sustain = 0;
            //note.PalmMute = 0;
            //note.HammerOn = 0;
            //note.Hopo = 0;

            return(note);
        }
        private static Tuple <int, SongChordTemplate2014> GetChordTemplate(ZpeChord zChord, Dictionary <string, Tuple <int, SongChordTemplate2014> > chordTemps)
        {
            Tuple <int, SongChordTemplate2014> val;

            if (!chordTemps.TryGetValue(HashChord(zChord), out val))
            {
                SongChordTemplate2014 templ = new SongChordTemplate2014()
                {
                    ChordName = "", DisplayName = ""
                };
                val           = new Tuple <int, SongChordTemplate2014>(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);
        }