protected override string InternalToString(Tune t)
        {
            var sb = new StringBuilder();

            foreach (var tuneElement in t.TuneElementList)
            {
                sb.Append(DurationConverter.ToString(tuneElement.Duration));

                var note = tuneElement as Note;
                if (note != null)
                {
                    sb.Append(PitchConverter.ToString(note.Pitch));
                    sb.Append((ScaleConverter.GetValue(note.Scale) - OffsetScale).ToString(CultureInfo.InvariantCulture));
                }
                else if (tuneElement is Pause)
                {
                    sb.Append(Pause);
                }

                if (tuneElement.Dotted)
                {
                    sb.Append(Dot);
                }

                sb.Append(TuneElementDelimiter);
            }

            return(sb.ToString());
        }
        protected override string InternalToString(Tune t)
        {
            var sb = new StringBuilder();

            sb.Append(t.Name);
            sb.Append(TuneCommandDelimiter);

            var defaultDuration = t.TuneElementList.GroupBy(g => g.Duration)
                                  .OrderByDescending(o => o.Count())
                                  .First().Key;

            var defaultScale = t.TuneElementList.OfType <Note>()
                               .GroupBy(g => g.Scale)
                               .OrderByDescending(o => o.Count())
                               .First().Key;

            sb.AppendFormat("d={0},o={1},b={2}",
                            DurationConverter.ToString(defaultDuration),
                            ScaleConverter.ToString(defaultScale),
                            t.Tempo.HasValue ? t.Tempo.Value.ToString(CultureInfo.InvariantCulture) : DefaultBpm.ToString());

            sb.Append(TuneCommandDelimiter);

            foreach (var tuneElement in t.TuneElementList)
            {
                if (tuneElement.Duration != defaultDuration)
                {
                    sb.Append(DurationConverter.ToString(tuneElement.Duration));
                }

                var note = tuneElement as Note;
                if (note != null)
                {
                    sb.Append(PitchConverter.ToString(note.Pitch));
                    if (note.Scale != defaultScale)
                    {
                        sb.Append(ScaleConverter.ToString(note.Scale));
                    }
                }
                else if (tuneElement is Pause)
                {
                    sb.Append(Pause);
                }

                if (tuneElement.Dotted)
                {
                    sb.Append(Dot);
                }

                sb.Append(TuneElementDelimiter);
            }

            return(sb.ToString());
        }
        protected override Tune InternalParse(string s)
        {
            var tuneElements = new List <TuneElement>();

            var regex = new Regex(TuneElementPattern, RegexOptions.IgnoreCase);

            foreach (Match match in regex.Matches(s))
            {
                var duration = DurationConverter.Parse(match.Groups[1].Value);

                TuneElement tuneElement = null;
                if (match.Groups[2].Value == Pause)
                {
                    tuneElement = new Pause(duration);
                }
                else
                {
                    var pitch = PitchConverter.Parse(match.Groups[2].Value);

                    var scale       = Scales.Four;
                    var scaleString = match.Groups[4].Value;
                    if (!string.IsNullOrWhiteSpace(scaleString))
                    {
                        int scaleInt;
                        if (int.TryParse(scaleString, out scaleInt))
                        {
                            scale = ScaleConverter.Parse((scaleInt + OffsetScale).ToString(CultureInfo.InvariantCulture));
                        }
                    }

                    tuneElement = new Note(pitch, scale, duration);
                }

                tuneElement.Dotted = match.Groups[3].Value == Dot;

                tuneElements.Add(tuneElement);
            }

            return(new Tune(tuneElements));
        }
 protected TuneConverter()
 {
     DurationConverter = new DurationConverter();
     ScaleConverter    = new ScaleConverter();
     PitchConverter    = new PitchConverter();
 }
        protected override Tune InternalParse(string s)
        {
            var parts = s.Split(TuneCommandDelimiter);

            if (parts.Count() < 2 || parts.Count() > 3)
            {
                throw new FormatException();
            }

            var name = parts[0];

            string notes;
            var    bpm             = DefaultBpm.ToString();
            var    defaultDuration = DefaultDuration;
            var    defaultScale    = DefaultScale;

            if (parts.Count() == 3)
            {
                notes = parts[2].ToUpperInvariant();

                var commandSection = parts[1];

                var bpmString = GetFirstValueGroup(commandSection, PatternDefaultBpm);
                if (!string.IsNullOrEmpty(bpmString))
                {
                    bpm = bpmString;
                }

                var durationString = GetFirstValueGroup(commandSection, PatternDefaultDuration);
                if (!string.IsNullOrEmpty(durationString))
                {
                    defaultDuration = durationString;
                }

                var scaleString = GetFirstValueGroup(commandSection, PatternDefaultScale);
                if (!string.IsNullOrEmpty(scaleString))
                {
                    defaultScale = scaleString;
                }
            }
            else
            {
                notes = parts[1].ToUpperInvariant();
            }

            var tuneElementList = new List <TuneElement>();
            var regexNotes      = new Regex(TuneElementPattern);
            var matches         = regexNotes.Matches(notes);

            foreach (Match m in matches)
            {
                var durationString = string.IsNullOrEmpty(m.Groups[1].Value) ? defaultDuration : m.Groups[1].Value;
                var pitchString    = m.Groups[2].Value;
                var dotted         = m.Groups[3].Value == ".";
                var scaleString    = string.IsNullOrEmpty(m.Groups[4].Value) ? defaultScale : m.Groups[4].Value;

                var duration = DurationConverter.Parse(durationString);
                var scale    = ScaleConverter.Parse(scaleString);

                TuneElement tuneElement;
                if (pitchString == Pause)
                {
                    tuneElement = new Pause(duration);
                }
                else
                {
                    var pitch = PitchConverter.Parse(pitchString);
                    tuneElement = new Note(pitch, scale, duration);
                }
                tuneElement.Dotted = dotted;
                tuneElementList.Add(tuneElement);
            }

            var tune = new Tune(tuneElementList, Convert.ToInt32(bpm));

            tune.Name = name;

            return(tune);
        }