public static List <MidiNote> GetNotes(Sequence sequence)
        {
            sequencer.Sequence = sequence;
            List <MidiNote> notes = new List <MidiNote>();

            foreach (Track track in sequence)
            {
                // Scan all of the notes
                for (int i = 0; i < track.Count; i++)
                {
                    MidiEvent midiEvent = track.GetMidiEvent(i);
                    if (midiEvent.MidiMessage.MessageType == MessageType.Channel)
                    {
                        var message = midiEvent.MidiMessage as ChannelMessage;
                        if (message.Data2 > 0 && message.Command == ChannelCommand.NoteOn)
                        {
                            MidiNote note = CreateNote(track, midiEvent, i);
                            notes.Add(note);
                        }
                    }
                }
            }
            notes.Sort((a, b) => a.Start.CompareTo(b.Start));
            return(SplitNotes(notes));
        }
        private static MidiNote CreateNote(Track track, MidiEvent startEvent, int i)
        {
            MidiEvent      endEvent = FindNoteOff(track, startEvent, i);
            ChannelMessage start    = startEvent.MidiMessage as ChannelMessage;
            ChannelMessage end      = endEvent.MidiMessage as ChannelMessage;
            MidiNote       midiNote = new MidiNote();
            float          volume   = Math.Min(1f, start.Data2 / 127f);

            midiNote.Note  = new MusicNote(Math.Max(0, start.Data1 - 12));           //, volume);
            midiNote.Start = TimeSpan.FromMilliseconds(sequencer.TicksToMilliseconds(startEvent.AbsoluteTicks));
            if (end == null)
            {
                midiNote.Duration = TimeSpan.FromMilliseconds(sequencer.TicksToMilliseconds(track.Length)) - midiNote.Start;
            }
            else
            {
                midiNote.Duration = TimeSpan.FromMilliseconds(sequencer.TicksToMilliseconds(endEvent.AbsoluteTicks)) - midiNote.Start;
            }
            return(midiNote);
        }
        private static List <MidiNote> SplitNotes(List <MidiNote> inputNotes)
        {
            List <MidiNote> outputNotes = new List <MidiNote>();
            //Dictionary<int, MidiNote> playingNotes = new Dictionary<int, MidiNote>();
            MidiNote lastNote = new MidiNote();

            for (int i = 0; i < inputNotes.Count; i++)
            {
                MidiNote note = inputNotes[i];

                /*foreach (var pair in playingNotes.ToArray()) {
                 *      int index = pair.Key;
                 *      MidiNote pNote = pair.Value;
                 *      if (note.Start >= pNote.End) {
                 *              playingNotes.Remove(index);
                 *      }
                 *      else {
                 *              outputNotes[index].End = note.Start;
                 *      }
                 * }*/
                if (i != 0 && lastNote.End > note.Start)
                {
                    lastNote.End = note.Start;
                    outputNotes[outputNotes.Count - 1] = lastNote;
                }
                //playingNotes.Add(i, note);
                outputNotes.Add(note);
            }
            for (int i = 0; i < outputNotes.Count; i++)
            {
                MidiNote note = outputNotes[i];
                if (note.Duration <= TimeSpan.Zero)
                {
                    outputNotes.RemoveAt(i);
                    i--;
                }
            }
            return(outputNotes);
        }
        private static void WriteNote(BinaryWriter writer, MidiNote note, PCMModifiers mods)
        {
            // Square wave
            MusicNote musicNote = note.Note;

            musicNote.Octave += mods.OctaveOffset;
            musicNote.Octave  = Math.Max(mods.MaxOctave, musicNote.Octave);
            int max   = (int)Math.Round(sbyte.MaxValue * note.Note.Volume * mods.Volume);
            int min   = (int)Math.Round(sbyte.MinValue * note.Note.Volume * mods.Volume);
            int range = max - min;
            //int halfRange = range / 2;
            float freq   = note.Note.Frequency;
            float period = mods.SampleRate / freq;
            int   start  = (int)Math.Round(note.Start.TotalSeconds * mods.SampleRate);
            int   length = (int)Math.Round(note.Duration.TotalSeconds * mods.SampleRate);

            writer.BaseStream.Position = start;
            bool up   = true;
            int  inc  = (int)Math.Round(period / 2);
            int  next = inc;

            for (int i = 0; i < length; i++)
            {
                int   sample;
                float dif = next - i;
                if (dif <= 0)
                {
                    up    = !up;
                    next += inc;
                    //dif++;
                    dif++;
                }
                if (dif >= 1)
                {
                    if (up)
                    {
                        sample = max;
                    }
                    else
                    {
                        sample = min;
                    }
                }
                else
                {
                    if (up != (dif >= 0.5f))
                    {
                        sample = max;
                    }
                    else
                    {
                        sample = min;
                    }

                    /*if (up)
                     *      sample = (int) (max - range * dif);
                     * else
                     *      sample = (int) (min + range * dif);*/
                }
                writer.Write(unchecked ((byte)(sample & 0xFF)));
            }
        }