// COMPLETE
        private static void WriteRocksmithSngPhraseIterations(EndianBinaryWriter w, SongPhraseIteration[] phraseIterations, Single songLength)
        {
            // Sample: begins at position 7,664 in NumberThirteen_Lead.sng

            // output header
            if (phraseIterations == null || phraseIterations.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }

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

            // output phrase iterations
            for (int i = 0; i < phraseIterations.Length; i++)
            {
                // phrase id
                w.Write(phraseIterations[i].PhraseId);
                // start time
                w.Write(phraseIterations[i].Time);
                // end time
                var endTime = i == phraseIterations.Length - 1
                    ? songLength
                    : phraseIterations[i + 1].Time;
                w.Write(endTime);
            }
        }
        // COMPLETE
        private static void WriteRocksmithSngPhrases(EndianBinaryWriter w, SongPhrase[] phrases, SongPhraseIteration[] phraseIterations)
        {
            // Sample: begins at position 7,208 in NumberThirteen_Lead.sng

            // output header
            if (phrases == null || phrases.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }

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

            // output phrases
            for (int i = 0; i < phrases.Length; i++)
            {
                // solo
                w.Write(phrases[i].Solo == 1 ? true : false);

                // disparity
                w.Write(phrases[i].Disparity == 1 ? true : false);

                // ignore
                w.Write(phrases[i].Ignore == 1 ? true : false);

                // unused padding
                w.Write(new byte());

                // maxDifficulty tag
                w.Write(phrases[i].MaxDifficulty);

                // count of usage in iterations
                int phraseIterationCount = 0;
                for (int i2 = 0; i2 < phraseIterations.Length; i2++)
                {
                    if (phraseIterations[i2].PhraseId == i)
                    {
                        phraseIterationCount++;
                    }
                }
                w.Write(phraseIterationCount);

                // name tag
                string name = phrases[i].Name;
                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]);
            }
        }
        // COMPLETE except hardcoded fields
        // Sample: begins at position 9,216 in NumberThirteen_Lead.sng
        private static void WriteRocksmithSngSections(EndianBinaryWriter w, Xml.SongSection[] sections, SongPhraseIteration[] phraseIterations, Single songLength)
        {
            // output header
            if (sections == null || sections.Length == 0)
            {
                w.Write(new byte[4]); // empty header
                return;
            }
            // output header count
            w.Write(sections.Length);

            // output sections
            for (int i = 0; i < sections.Length; i++)
            {
                // section name
                string name = sections[i].Name;
                if (name.Length > 32)
                {
                    name = name.Substring(0, 32);
                }
                foreach (char c in name)
                {
                    w.Write(Convert.ToByte(c));
                }
                // padding after section name
                w.Write(new byte[32 - name.Length]);

                // number tag
                w.Write(sections[i].Number);

                // start time
                w.Write(sections[i].StartTime);

                // end time
                var endTime = i == sections.Length - 1
                    ? songLength
                    : sections[i + 1].StartTime;
                w.Write(endTime);

                // phrase iteration start index
                bool phraseIterationFound = false;
                for (int p = 0; p < phraseIterations.Length; p++)
                {
                    if (sections[i].StartTime <= phraseIterations[p].Time)
                    {
                        w.Write(p);
                        phraseIterationFound = true;
                        break;
                    }
                }
                if (!phraseIterationFound)
                    throw new Exception(string.Format("No phrase iteration found with matching time for section {0}.", i.ToString()));

                // phrase iteration end index
                if (i == sections.Length - 1) // if last section, default to last phrase iteration
                {
                    w.Write(phraseIterations.Length - 1);
                }
                else
                {
                    //bool endPhraseIterationFound = false;
                    for (int p = 0; p < phraseIterations.Length; p++)
                    {
                        if (sections[i + 1].StartTime <= phraseIterations[p].Time)
                        {
                            w.Write(Convert.ToInt32(p - 1));
                            //endPhraseIterationFound = true;
                            break;
                        }
                    }
                    //if (!endPhraseIterationFound)
                    //    throw new Exception(string.Format("No end phrase iteration found with matching time for section {0}.", i.ToString()));
                }

                // series of 8 unknown bytes (look like flags)? below logic is wrong, just defaulting for now
                w.Write(true);
                w.Write(true);
                w.Write(true);
                w.Write(true);
                w.Write(true);
                w.Write(false);
                w.Write(false);
                w.Write(false);
            }
        }