private LinkedList <Data.Intermediate.Event.TimeSignature> ConvertTimeSignature(LinkedList <Data.MIDI.Event.Event> events, int timeDivision)
        {
            var pos = new Data.Intermediate.Position(1, 0);

            var tsl = new LinkedList <Data.Intermediate.Event.TimeSignature>();

            tsl.AddFirst(new Data.Intermediate.Event.TimeSignature(pos.Clone(), pos.Clone(), 4, 4, ((uint)timeDivision * 4)));    // Set defalt time signature (4/4)

            foreach (Data.MIDI.Event.Event ev in events)
            {
                pos = new Data.Intermediate.Position(pos, ev.DeltaTime, tsl.Last);

                if (ev is Data.MIDI.Event.TimeSignature)
                {
                    var newEv = (Data.MIDI.Event.TimeSignature)ev;

                    Data.Intermediate.Position oldPos = pos.Clone();
                    if (pos.Tick != 0)  // skip if pos(x : 0)
                    {
                        pos = new Data.Intermediate.Position((pos.Bar + 1), 0);
                    }

                    var newTS = new Data.Intermediate.Event.TimeSignature(pos.Clone(), oldPos, newEv.Numerator, (1 << newEv.DenominatorBitShift), ((uint)(timeDivision >> (newEv.DenominatorBitShift - 2)) * (uint)newEv.Numerator));
                    if (tsl.Last.Value.Position.CompareTo(newTS.PrevSignedPosition) == 0)
                    {
                        tsl.RemoveLast();
                    }
                    tsl.AddLast(newTS);
                }
            }

            return(tsl);
        }
        private Data.Intermediate.Track ConvertTrack(Data.MIDI.Track midiTrack, LinkedListNode <Data.Intermediate.Event.TimeSignature> tsNode, int trackNumber)
        {
            var pos = new Data.Intermediate.Position(1, 0);

            var    nl     = new List <Data.Intermediate.Notes>();
            var    il     = new LinkedList <Data.Intermediate.Event.Instrument>();
            var    vl     = new LinkedList <Data.Intermediate.Event.Volume>();
            var    pl     = new LinkedList <Data.Intermediate.Event.Pan>();
            string name   = string.Empty;
            var    length = new Data.Intermediate.Position(1, 0);

            foreach (Data.MIDI.Event.Event ev in midiTrack.EventList)
            {
                pos = new Data.Intermediate.Position(pos, ev.DeltaTime, tsNode);
                while (tsNode.Next != null && pos.CompareTo(tsNode.Next.Value.Position) >= 0)       // Go to proper node
                {
                    tsNode = tsNode.Next;
                }

                if (ev is Data.MIDI.Event.NoteOn)
                {
                    FuncNoteOn(nl, pos.Clone(), (Data.MIDI.Event.NoteOn)ev);
                }
                else if (ev is Data.MIDI.Event.NoteOff)
                {
                    FuncNoteOff(nl, pos.Clone(), (Data.MIDI.Event.NoteOff)ev);
                }
                else if (ev is Data.MIDI.Event.ProgramChange)
                {
                    var inst = (Data.MIDI.Event.ProgramChange)ev;
                    il.AddLast(new Data.Intermediate.Event.Instrument(pos.Clone(), inst.Number));
                }
                else if (ev is Data.MIDI.Event.Volume)
                {
                    var vol = (Data.MIDI.Event.Volume)ev;
                    vl.AddLast(new Data.Intermediate.Event.Volume(pos.Clone(), vol.Value));
                }
                else if (ev is Data.MIDI.Event.Pan)
                {
                    var pan = (Data.MIDI.Event.Pan)ev;
                    pl.AddLast(new Data.Intermediate.Event.Pan(pos.Clone(), pan.Value));
                }
                else if (ev is Data.MIDI.Event.SequenceTrackName)
                {
                    var stn = (Data.MIDI.Event.SequenceTrackName)ev;
                    name = stn.Name;
                }
                else if (ev is Data.MIDI.Event.EndOfTrack)
                {
                    length = pos.Clone();
                }
            }

            return(new Data.Intermediate.Track(nl, il, vl, pl, trackNumber, length, name));
        }
 private void FuncNoteOff(List <Data.Intermediate.Notes> nl, Data.Intermediate.Position position, Data.MIDI.Event.NoteOff ev)
 {
     foreach (Data.Intermediate.Notes notes in nl)
     {
         Data.Intermediate.Event.Note note = (Data.Intermediate.Event.Note)notes.NoteList.Last.Value;
         if (note.End == null && note.KeyNumber == ev.Number)
         {
             note.End = position;
             return;
         }
     }
 }
        private void FuncNoteOn(List <Data.Intermediate.Notes> nl, Data.Intermediate.Position position, Data.MIDI.Event.NoteOn ev)
        {
            foreach (Data.Intermediate.Notes notes in nl)
            {
                LinkedList <Data.Intermediate.Event.NoteRest> list = notes.NoteList;
                if (list.Last.Value.End != null)        // Check note overlapping
                {
                    list.AddLast(new Data.Intermediate.Event.Note(position, null, ev.Number, ev.Velocity));
                    return;
                }
            }

            // Create new notelist
            var newList = new LinkedList <Data.Intermediate.Event.NoteRest>();

            newList.AddFirst(new Data.Intermediate.Event.Note(position, null, ev.Number, ev.Velocity));
            nl.Add(new Data.Intermediate.Notes(newList, nl.Count));
        }
        private List <int> ConvertLengthFormat(Data.Intermediate.Position posdata, int[][] lentable)
        {
            var  lenList = new List <int>();
            uint bar     = posdata.Bar;
            uint tick    = posdata.Tick;

            for (; bar > 0; bar--)
            {
                lenList.AddRange(lentable[0]);
            }

            if (tick > 0)
            {
                lenList.AddRange(lentable[tick]);
            }

            return(lenList);
        }
        private void ConvertConductorTrack(Data.MIDI.Track midiTrack, DataSet set, int timeDivision)
        {
            LinkedList <Data.MIDI.Event.Event> events = midiTrack.EventList;

            set.TimeSignatureList = ConvertTimeSignature(events, timeDivision);

            var pos = new Data.Intermediate.Position(1, 0);
            LinkedListNode <Data.Intermediate.Event.TimeSignature> tsNode = set.TimeSignatureList.First;

            var ksl = new LinkedList <Data.Intermediate.Event.KeySignature>();

            ksl.AddFirst(new Data.Intermediate.Event.KeySignature(pos.Clone(), Key.CMaj));      // Set default key signature
            var tl = new LinkedList <Data.Intermediate.Event.Tempo>();

            tl.AddFirst(new Data.Intermediate.Event.Tempo(pos.Clone(), 120));       // Set default tempo
            string title  = string.Empty;
            var    length = new Data.Intermediate.Position(1, 0);

            foreach (Data.MIDI.Event.Event ev in events)
            {
                pos = new Data.Intermediate.Position(pos, ev.DeltaTime, tsNode);
                while (tsNode.Next != null && pos.CompareTo(tsNode.Next.Value.Position) >= 0)       // Go to proper node
                {
                    tsNode = tsNode.Next;
                }

                if (ev is Data.MIDI.Event.SetTempo)
                {
                    var st    = (Data.MIDI.Event.SetTempo)ev;
                    var newST = new Data.Intermediate.Event.Tempo(pos.Clone(), (60000000 / st.Value));
                    if (tl.Last.Value.Position.CompareTo(newST.Position) == 0)
                    {
                        tl.RemoveLast();
                    }
                    tl.AddLast(newST);
                }
                else if (ev is Data.MIDI.Event.KeySignature)
                {
                    var ks    = (Data.MIDI.Event.KeySignature)ev;
                    var newKS = new Data.Intermediate.Event.KeySignature(pos.Clone(), Tables.KeyTable[ks.MinorFlagNumber, ks.SignatureNumber]);
                    if (ksl.Last.Value.Position.CompareTo(newKS.Position) == 0)
                    {
                        ksl.RemoveLast();
                    }
                    ksl.AddLast(newKS);
                }
                else if (ev is Data.MIDI.Event.SequenceTrackName)
                {
                    var stn = (Data.MIDI.Event.SequenceTrackName)ev;
                    title = stn.Name;
                }
                else if (ev is Data.MIDI.Event.EndOfTrack)
                {
                    length = pos.Clone();
                }
            }

            set.TrackList.Add(new Data.Intermediate.Track(
                                  new List <Data.Intermediate.Notes>(),
                                  new LinkedList <Data.Intermediate.Event.Instrument>(),
                                  new LinkedList <Data.Intermediate.Event.Volume>(),
                                  new LinkedList <Data.Intermediate.Event.Pan>(),
                                  0,
                                  length,
                                  "Conductor Track"
                                  ));
            set.TempoList        = tl;
            set.KeySignatureList = ksl;
            set.Title            = title;
        }
        private List <Data.MML.Part> CreatePartList(Data.Intermediate.Intermediate intermediate, Settings settings, List <Data.Intermediate.NotesStatus> statusList)
        {
            int[][] lentable = CreateLengthTable((uint)settings.mmlExpression.TimeBase, settings.noteRest);


            var partList = new List <Data.MML.Part>();

            LinkedListNode <Data.Intermediate.Event.Tempo> tempoNode = intermediate.TempoList.First;

            foreach (Data.Intermediate.Track track in intermediate.TrackList)
            {
                Data.Intermediate.Notes       notes  = track.NotesList[0];
                Data.Intermediate.NotesStatus status = statusList.Find(x => (x.TrackNumber == track.Number && x.NumberInTrack == notes.NumberInTrack));

                LinkedListNode <Data.Intermediate.Event.NoteRest>      noteNode = notes.NoteList.First;
                LinkedListNode <Data.Intermediate.Event.Instrument>    instNode = track.InstrumentList.First;
                LinkedListNode <Data.Intermediate.Event.Volume>        volNode  = track.VolumeList.First;
                LinkedListNode <Data.Intermediate.Event.Pan>           panNode  = track.PanList.First;
                LinkedListNode <Data.Intermediate.Event.KeySignature>  ksNode   = intermediate.KeySignatureList.First;
                LinkedListNode <Data.Intermediate.Event.TimeSignature> tsNode   = intermediate.TimeSignatureList.First;

                int barCnt  = 1;
                Key key     = Key.CMaj;
                var barList = new List <Data.MML.Bar>();

                for (int i = 1; i <= track.Length.Bar; i++)
                {
                    var  comList  = new LinkedList <Data.MML.Command.Command>();
                    bool prevTied = false;

                    MMLCommandRelation relation = MMLCommandRelation.Clear;
                    while (true)
                    {
                        string addCommandName;
                        if (intermediate.TrackList.IndexOf(track) == 0)
                        {
                            addCommandName = GetEarliestCommandName(ksNode?.Value, tempoNode?.Value, instNode?.Value, volNode?.Value, panNode?.Value, noteNode?.Value, i, prevTied, settings);
                        }
                        else
                        {
                            addCommandName = GetEarliestCommandName(ksNode?.Value, null, instNode?.Value, volNode?.Value, panNode?.Value, noteNode?.Value, i, prevTied, settings);
                        }

                        Data.MML.Command.Command addCommand = null;
                        if (addCommandName == typeof(Data.Intermediate.Event.KeySignature).Name)
                        {
                            key    = ksNode.Value.Key;
                            ksNode = ksNode.Next;
                            continue;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Tempo).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation |= MMLCommandRelation.NextControl;
                            }

                            addCommand = CreateTempoInstance(tempoNode.Value.Value, relation);

                            relation |= MMLCommandRelation.PrevControl;
                            tempoNode = tempoNode.Next;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Instrument).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation |= MMLCommandRelation.NextControl;
                            }

                            addCommand = CreateInstrumentInstance(instNode.Value.Value, relation);

                            relation |= MMLCommandRelation.PrevControl;
                            instNode  = instNode.Next;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Volume).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation |= MMLCommandRelation.NextControl;
                            }

                            addCommand = CreateVolumeInstance(volNode.Value.Value, relation);

                            relation |= MMLCommandRelation.PrevControl;
                            volNode   = volNode.Next;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Pan).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation |= MMLCommandRelation.NextControl;
                            }

                            addCommand = CreatePanInstance(panNode.Value.Value, relation);

                            relation |= MMLCommandRelation.PrevControl;
                            panNode   = panNode.Next;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Note).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation &= ~MMLCommandRelation.NextControl;
                            }

                            var note = (Data.Intermediate.Event.Note)noteNode.Value;
                            Data.Intermediate.Position poslen = CalculateLength(note.Start, note.End, intermediate.TimeSignatureList, (int)settings.mmlExpression.TimeBase);
                            List <int>         length         = ConvertLengthFormat(poslen, lentable);
                            MMLCommandRelation tempRel        = relation;
                            if (note.TieFlag)
                            {
                                tempRel  |= MMLCommandRelation.TieAfter;
                                relation |= MMLCommandRelation.TieBefore;
                            }
                            else
                            {
                                tempRel  &= ~MMLCommandRelation.TieAfter;
                                relation &= ~MMLCommandRelation.TieBefore;
                            }

                            addCommand = CreateNoteInstance((note.KeyNumber / 12 - 1), Tables.NoteNameDictionary[key][note.KeyNumber % 12], length, tempRel);

                            relation &= ~MMLCommandRelation.PrevControl;
                            prevTied  = note.TieFlag;
                            noteNode  = noteNode.Next;
                        }
                        else if (addCommandName == typeof(Data.Intermediate.Event.Rest).Name)
                        {
                            if (comList.Count > 0)
                            {
                                comList.Last.Value.CommandRelation &= ~MMLCommandRelation.NextControl;
                            }

                            var rest = (Data.Intermediate.Event.Rest)noteNode.Value;
                            Data.Intermediate.Position poslen = CalculateLength(rest.Start, rest.End, intermediate.TimeSignatureList, (int)settings.mmlExpression.TimeBase);
                            List <int> length = ConvertLengthFormat(poslen, lentable);

                            MMLCommandRelation tempRel = relation;
                            if (rest.TieFlag)
                            {
                                tempRel  |= MMLCommandRelation.TieAfter;
                                relation |= MMLCommandRelation.TieBefore;
                            }
                            else
                            {
                                tempRel  &= ~MMLCommandRelation.TieAfter;
                                relation &= ~MMLCommandRelation.TieBefore;
                            }

                            addCommand = CreateRestInstance(length, tempRel);

                            relation &= ~MMLCommandRelation.PrevControl;
                            prevTied  = rest.TieFlag;
                            noteNode  = noteNode.Next;
                        }
                        else
                        {
                            break;
                        }

                        comList.AddLast(addCommand);
                    }


                    if (settings.mmlExpression.NewBlockByBar == 1 && i == tsNode.Value.Position.Bar)
                    {
                        barCnt = 1;
                    }
                    else
                    {
                        barCnt++;
                    }

                    uint nextTSBar = (tsNode.Next?.Value.Position.Bar ?? 0);
                    if (i + 1 == nextTSBar)
                    {
                        tsNode = tsNode.Next;
                    }
                    string seperateSign = GetSeperateSign(i, barCnt, nextTSBar, settings.mmlExpression);


                    barList.Add(new Data.MML.Bar(comList, i, seperateSign));
                }

                if (track.Length.Tick == 0)
                {
                    Data.MML.Bar lastBar = barList.Last();
                    if (lastBar.CommandList.Count == 0)
                    {
                        barList.Remove(lastBar);
                    }
                }


                partList.Add(new Data.MML.Part(barList, status.SoundModule, track.Name));
            }


            return(partList);
        }
        private Data.Intermediate.Position CalculateLength
        (
            Data.Intermediate.Position start,
            Data.Intermediate.Position end,
            LinkedList <Data.Intermediate.Event.TimeSignature> tsList,
            int countsPerWholeNote
        )
        {
            // Search current time signature
            LinkedListNode <Data.Intermediate.Event.TimeSignature> curTSNode = tsList.First;

            while (true)
            {
                if (curTSNode.Value.Position.CompareTo(start) < 0)
                {
                    if (curTSNode.Next == null)
                    {
                        break;
                    }
                    else
                    {
                        curTSNode = curTSNode.Next;
                    }
                }
                else if (curTSNode.Value.Position.CompareTo(start) == 0)
                {
                    break;
                }
                else
                {
                    curTSNode = curTSNode.Previous;
                    break;
                }
            }

            // Calculate length data by Position
            Data.Intermediate.Position len       = new Data.Intermediate.Position(0, 0);
            Data.Intermediate.Position tempStart = start;
            LinkedListNode <Data.Intermediate.Event.TimeSignature> nextTSNode = curTSNode.Next;

            while (true)
            {
                if (nextTSNode == null)
                {
                    Data.Intermediate.Position sub  = end.Subtract(tempStart, curTSNode.Value.TickPerBar);
                    Data.Intermediate.Position sub2 = Data.Intermediate.Position.ConvertByTicksPerBar(sub, curTSNode.Value.TickPerBar, (uint)countsPerWholeNote);
                    len = len.Add(sub2, (uint)countsPerWholeNote);
                    break;
                }
                else
                {
                    if (nextTSNode.Value.PrevSignedPosition.CompareTo(end) >= 0)
                    {
                        Data.Intermediate.Position sub  = end.Subtract(tempStart, curTSNode.Value.TickPerBar);
                        Data.Intermediate.Position sub2 = Data.Intermediate.Position.ConvertByTicksPerBar(sub, curTSNode.Value.TickPerBar, (uint)countsPerWholeNote);
                        len = len.Add(sub2, (uint)countsPerWholeNote);
                        break;
                    }
                    else
                    {
                        Data.Intermediate.Position sub  = nextTSNode.Value.PrevSignedPosition.Subtract(tempStart, curTSNode.Value.TickPerBar);
                        Data.Intermediate.Position sub2 = Data.Intermediate.Position.ConvertByTicksPerBar(sub, curTSNode.Value.TickPerBar, (uint)countsPerWholeNote);
                        len        = len.Add(sub2, (uint)countsPerWholeNote);
                        tempStart  = nextTSNode.Value.Position;
                        curTSNode  = curTSNode.Next;
                        nextTSNode = nextTSNode.Next;
                    }
                }
            }

            return(len);
        }