Exemplo n.º 1
0
        /* create a new interval MIDI track */
        public static IntervalTrackRec NewIntervalTrack()
        {
            IntervalTrackRec Track = new IntervalTrackRec();

            Track.EventList = new List <IntEventRec>();
            return(Track);
        }
Exemplo n.º 2
0
        /* insert new event into track sorted */
        public static void IntervalTrackInsertEventSorted(
            IntervalTrackRec Track,
            IntEventRec Event)
        {
            int OurEventStartTime = GetIntervalEventTime(Event);
            int Scan = Track.EventList.Count - 1;

            while (Scan >= 0)
            {
                IntEventRec OtherEvent = Track.EventList[Scan];
                if (GetIntervalEventTime(OtherEvent) <= OurEventStartTime)
                {
                    Track.EventList.Insert(Scan + 1, Event);
                    return;
                }
                Scan -= 1;
            }
            Track.EventList.Insert(0, Event);
        }
Exemplo n.º 3
0
        /* import midi file from existing file pointer */
        public static void ImportMIDIFileSpecified(string Where)
        {
            RawMIDIScoreRec Score = NewRawMIDIScore();

            using (Stream stream = new FileStream(Where, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.BufferSize))
            {
                using (BinaryReader BufferedFile = new BinaryReader(stream))
                {
                    MIDIParseErrorType result = MIDIParseErrorType.eMIDIParseFileReadError;
                    try
                    {
                        result = ParseMIDIFile(BufferedFile, Score);
                    }
                    catch (InvalidDataException)
                    {
                        // generally - unexpected eof
                        Debug.Assert(result == MIDIParseErrorType.eMIDIParseFileReadError);
                    }
                    switch (result)
                    {
                    default:
                        Debug.Assert(false);
                        throw new ArgumentException();

                    case MIDIParseErrorType.eMIDIParseNoError:
                        break;

                    case MIDIParseErrorType.eMIDIParseFileReadError:
                        MessageBox.Show(
                            "An error occurred while reading the file. Attempting to import as much of the file as possible.",
                            "Import Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        break;

                    case MIDIParseErrorType.eMIDIParseBadFormat:
                        MessageBox.Show(
                            "The file is not a valid MIDI file. Attempting to import as much of the file as possible.",
                            "Import Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        break;
                    }
                }
            }
            if (GetRawMIDIScoreNumTracks(Score) > 0)
            {
                /* create the new document to put the tracks into */
                bool     TrackWasCreated = false;
                Document Document        = new Document();

                /* iterate over MIDI tracks */
                int TrackLimit = GetRawMIDIScoreNumTracks(Score);
                for (int TrackScan = 0; TrackScan < TrackLimit; TrackScan++)
                {
                    /* get track */
                    RawMIDITrackRec Track = GetRawMIDIScoreIndexedTrack(Score, TrackScan);

                    /* process channels */
                    for (short ChannelScan = 1; ChannelScan <= 16; ChannelScan++)
                    {
                        bool             KeepFlag;
                        IntervalTrackRec IntervalTrack = NewIntervalTrack();
                        ConvertRawToInterval(Track, IntervalTrack, ChannelScan, out KeepFlag);

                        /* process cooked track into one of our track objects */
                        if (KeepFlag)
                        {
                            QuantizedTrackRec QuantizedTrack;
                            TrackObjectRec    DocumentTrack;

                            /* make sure we can handle this track */
                            if (MIDITimingType.eMIDIMeteredTime != RawMIDIScoreGetTimingMode(Score))
                            {
                                MessageBox.Show(
                                    "Can't import real-time MIDI files.",
                                    "Import Error",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Stop);
                                return;
                            }

                            QuantizedTrack = NewQuantizedTrack();
                            ConvertIntervalToQuantized(IntervalTrack, QuantizedTrack,
                                                       RawMIDIScoreGetPartsPerQuarterNote(Score));

                            DocumentTrack = new TrackObjectRec(Document);
                            Document.TrackList.Add(DocumentTrack);
                            TrackWasCreated = true;
                            ConvertQuantToNote(QuantizedTrack, DocumentTrack);

                            /* set track release point 1 to be from end */
                            DocumentTrack.DefaultReleasePoint1ModeFlag = NoteFlags.eRelease1FromEnd;
                        }
                    }
                }

                /* clear the dirty flag, since nothing was actually modified */
                Document.Modified = false;

                /* remove track if we didn't actually find anything in the file */
                if (!TrackWasCreated)
                {
                    MessageBox.Show(
                        "No tracks were found in the MIDI file.",
                        "Import Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                    return;
                }

                MainWindow MainWindow = new MainWindow(Document, null);
                MainWindow.Show();
            }
        }
Exemplo n.º 4
0
 /* get an indexed event from the track */
 public static IntEventRec GetIntervalTrackIndexedEvent(
     IntervalTrackRec Track,
     int Index)
 {
     return(Track.EventList[Index]);
 }
Exemplo n.º 5
0
 /* get the number of events in the track */
 public static int GetIntervalTrackLength(IntervalTrackRec Track)
 {
     return(Track.EventList.Count);
 }
        /* convert raw track into an interval track.  MIDITrackNum should be in 1..16 */
        /* *KeepFlag is set if there were real events in this track. */
        public static void ConvertRawToInterval(
            RawMIDITrackRec RawTrack,
            IntervalTrackRec IntervalTrack,
            short MIDITrackNum,
            out bool KeepFlag)
        {
            int Limit;

            PitchEventRec[] EventTracker = new PitchEventRec[128];

            Debug.Assert((MIDITrackNum >= 1) || (MIDITrackNum <= 16));
            MIDITrackNum -= 1;
            KeepFlag      = false;

            /* initialize correlation tracker */
            for (int i = 0; i < 128; i += 1)
            {
                EventTracker[i].NoteOn = false;
            }

            /* scan all low level events */
            Limit = GetRawMIDITrackLength(RawTrack);
            for (int i = 0; i < Limit; i += 1)
            {
                byte TypeByte;

                RawMIDIEventRec RawEvent   = GetRawMIDITrackIndexedEvent(RawTrack, i);
                byte            StatusByte = GetRawMIDIEventStatus(RawEvent);
                switch ((StatusByte >> 4) & 0x0f)
                {
                /* ignore events we don't know about */
                default:
                    break;

                /* 1000nnnn:  note off event for channel nnnn followed by 2 data bytes */
                case 0x08:
NoteOffPoint:
                    if ((StatusByte & 0x0f) == MIDITrackNum)
                    {
                        short Pitch;
                        short ReleaseVelocity;

                        /* data byte 1:  velocity 0..127 */
                        /* data byte 2:  pitch 0..127 */
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            ReleaseVelocity = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 1));
                        }
                        else
                        {
                            ReleaseVelocity = 0;
                        }
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 1)
                        {
                            Pitch = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 0));
                        }
                        else
                        {
                            Pitch = 0;
                        }
                        if (EventTracker[Pitch].NoteOn)
                        {
                            IntEventRec IntervalEvent = NewIntervalNoteEvent(
                                EventTracker[Pitch].StartTime,
                                GetRawMIDIEventTime(RawEvent) - EventTracker[Pitch].StartTime,
                                Pitch,
                                EventTracker[Pitch].StartVelocity,
                                ReleaseVelocity);
                            IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                            EventTracker[Pitch].NoteOn = false;
                        }
                        else
                        {
                            /* no note-on event? */
                        }
                        KeepFlag = true;
                    }
                    break;

                /* 1001nnnn:  note on event for channel nnnn followed by 2 data bytes */
                case 0x09:
                    if ((StatusByte & 0x0f) == MIDITrackNum)
                    {
                        short Pitch;
                        short Velocity;

                        /* data byte 1:  velocity 0..127 */
                        /* data byte 2:  pitch 0..127 */
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            Velocity = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 1));
                        }
                        else
                        {
                            Velocity = 64;
                        }
                        if (Velocity == 0)
                        {
                            /* note on velocity 0 actually means note off */
                            goto NoteOffPoint;
                        }
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 1)
                        {
                            Pitch = (short)(0x7f & GetRawMIDIEventMessageByte(RawEvent, 0));
                        }
                        else
                        {
                            Pitch = 0;
                        }
                        if (!EventTracker[Pitch].NoteOn)
                        {
                            EventTracker[Pitch].StartTime     = GetRawMIDIEventTime(RawEvent);
                            EventTracker[Pitch].StartVelocity = Velocity;
                            EventTracker[Pitch].NoteOn        = true;
                        }
                        else
                        {
                            /* note already on? */
                        }
                        KeepFlag = true;
                    }
                    break;

                /* 1010nnnn:  polyphonic key pressure/after touch followed by */
                /*   2 data bytes */
                case 0x0a:
                    break;

                /* 1011nnnn:  control change followed by 2 data bytes */
                case 0x0b:
                    break;

                /* 1110nnnn:  pitch bend change followed by 2 data bytes */
                case 0x0e:
                    break;

                /* 1100nnnn:  program change followed by 1 data byte */
                case 0x0c:
                    break;

                /* 1101nnnn:  channel pressure/after touch followed by 1 data byte */
                case 0x0d:
                    break;

                /* assorted thangs */
                case 0x0f:
                    switch (StatusByte & 0x0f)
                    {
                    default:
                        break;

                    /* 11110000:  initial or solitary SYSEX message.  followed by a */
                    /*   variable length field.  solitary message is terminated by */
                    /*   0xf7 (which is not part of the message, but is included in */
                    /*   length).  continuing message does not end with 0xf7. */
                    /*   NOTE:  SYSEX also cancels the running status. */
                    /* 11110111:  continuing SYSEX message.  same format as initial. */
                    case 0x00:
                    case 0x07:
                    {
                        StringBuilder sb = new StringBuilder();
                        if ((StatusByte & 0x0f) == 0x00)
                        {
                            sb.AppendLine("System Exclusive $F0");
                        }
                        else
                        {
                            sb.AppendLine("System Exclusive $F7");
                        }
                        int c = GetRawMIDIEventMessageLength(RawEvent);
                        for (int j = 0; j < c; j += 1)
                        {
                            byte b = GetRawMIDIEventMessageByte(RawEvent, j);
                            sb.Append('$');
                            sb.Append(HexBuf[(b >> 4) & 0x0f]);
                            sb.Append(HexBuf[b & 0x0f]);
                            if (((j + 1) % SYSEXBYTESPERLINE) == 0)
                            {
                                sb.AppendLine();
                            }
                            else
                            {
                                sb.Append(' ');
                            }
                        }
                        IntEventRec IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), sb.ToString());
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110010:  song position pointer, followed by 2 data bytes */
                    case 0x02:
                    {
                        StringBuilder String;
                        string        Buffer;
                        IntEventRec   IntervalEvent;

                        String = new StringBuilder();
                        String.Append("Song Position Pointer" + Environment.NewLine);
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            String.Append((int)((GetRawMIDIEventMessageByte(RawEvent, 0) & 0x7f)
                                                | ((GetRawMIDIEventMessageByte(RawEvent, 1) & 0x7f) << 7)));
                        }
                        else
                        {
                            String.Append((int)0);
                        }
                        Buffer        = String.ToString();
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Buffer);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110011:  song select, followed by 2 data bytes */
                    case 0x03:
                    {
                        StringBuilder String;
                        string        Buffer;
                        IntEventRec   IntervalEvent;

                        String = new StringBuilder();
                        String.Append("Song Select" + Environment.NewLine);
                        if (GetRawMIDIEventMessageLength(RawEvent) >= 2)
                        {
                            String.Append((int)((GetRawMIDIEventMessageByte(RawEvent, 0) & 0x7f)
                                                | ((GetRawMIDIEventMessageByte(RawEvent, 1) & 0x7f) << 7)));
                        }
                        else
                        {
                            String.Append((int)0);
                        }
                        Buffer        = String.ToString();
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Buffer);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11110110:  tune request, no data */
                    case 0x06:
                    {
                        string      String;
                        IntEventRec IntervalEvent;

                        String        = "Tune Request";
                        IntervalEvent = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), String);
                        IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                    }
                    break;

                    /* 11111111:  meta event.  followed by type byte (0..127) and */
                    /*   then variable length specifier, then data bytes. */
                    case 0x0f:
                        /* check out the auxilliary type */
                        TypeByte = GetRawMIDIEventTypeByte(RawEvent);
                        switch (TypeByte)
                        {
                        default:
                            break;

                        /* (FF) 01 <len> <text>:  text event */
                        /* (FF) 02 <len> <text>:  copyright */
                        /* (FF) 03 <len> <text>:  sequence/track name */
                        /* (FF) 04 <len> <text>:  instrument name */
                        /* (FF) 05 <len> <text>:  lyric */
                        /* (FF) 06 <len> <text>:  marker */
                        /* (FF) 07 <len> <text>:  cue point */
                        case 0x01:
                        case 0x02:
                        case 0x03:
                        case 0x04:
                        case 0x05:
                        case 0x06:
                        case 0x07:
                        {
                            string      String;
                            char[]      Text;
                            IntEventRec IntervalEvent;
                            string      Combined;
                            int         Length;
                            int         Scan2;

                            switch (GetRawMIDIEventTypeByte(RawEvent))
                            {
                            default:
                                Debug.Assert(false);
                                throw new InvalidOperationException();

                            /* (FF) 01 <len> <text>:  text event */
                            /* (FF) 02 <len> <text>:  copyright */
                            /* (FF) 03 <len> <text>:  sequence/track name */
                            /* (FF) 04 <len> <text>:  instrument name */
                            /* (FF) 05 <len> <text>:  lyric */
                            /* (FF) 06 <len> <text>:  marker */
                            /* (FF) 07 <len> <text>:  cue point */
                            case 0x01:
                                String = "Comment" + Environment.NewLine;
                                break;

                            case 0x02:
                                String = "Copright" + Environment.NewLine;
                                break;

                            case 0x03:
                                String = "Track Name" + Environment.NewLine;
                                break;

                            case 0x04:
                                String = "Instrument Name" + Environment.NewLine;
                                break;

                            case 0x05:
                                String = "Lyric" + Environment.NewLine;
                                break;

                            case 0x06:
                                String = "Marker" + Environment.NewLine;
                                break;

                            case 0x07:
                                String = "Cue Point" + Environment.NewLine;
                                break;
                            }
                            Length = GetRawMIDIEventMessageLength(RawEvent);
                            if (Length > 0)
                            {
                                /* don't deal with the first character since it */
                                /* isn't part of the text */
                                Length -= 1;
                            }
                            Text = new char[Length + Environment.NewLine.Length];
                            for (Scan2 = 0; Scan2 < Length; Scan2 += 1)
                            {
                                Text[Scan2] = (char)GetRawMIDIEventMessageByte(RawEvent, Scan2 + 1 /*skip first character*/);
                            }
                            Text[Length]     = Environment.NewLine[0];
                            Text[Length + 1] = Environment.NewLine[1];
                            Combined         = String.Concat(String, new String(Text));
                            IntervalEvent    = NewIntervalCommentEvent(GetRawMIDIEventTime(RawEvent), Combined);
                            IntervalTrackInsertEventSorted(IntervalTrack, IntervalEvent);
                        }
                        break;

                            /* (FF) 00 <02> ss ss:  sequence number */
                            /* (FF) 2F <00>:  end of track */
                            /* (FF) 51 <03> tt tt tt:  set tempo (microsec/quarter note) */
                            /* (FF) 54 <05> hr mn se fr ff:  SMTPE offset */
                            /* (FF) 58 <04> nn dd cc bb: time signature */
                            /*    nn/dd is numerator/denominator.  dd is a negative power */
                            /*    of two (2=quarter note, 3=eighth note). */
                            /*    cc = midi clocks per metronome click. */
                            /*    bb = number of 32nd notes per quarter note (24 clocks) */
                            /* (FF) 59 <02> sf mi:  key signature */
                            /*    sf: -7..-1 flats, 0 = normal, 1..7 = sharps */
                            /*    mi = 0 or major, 1 for minor */
                            /* (FF) 7F <len> <data>:  sequencer meta event */
                        }
                        break;
                    }
                    break;
                }
            }
        }
Exemplo n.º 7
0
        /* convert interval track into quantized track. */
        public static bool ConvertIntervalToQuantized(
            IntervalTrackRec IntervalTrack,
            QuantizedTrackRec QuantizedTrack,
            int MidiQuarterNote)
        {
            int Scan;
            int Limit;

            TimeMatchRec[] MatchingTable = new TimeMatchRec[4 /*divisions*/ * 2 /*dot*/ * 9 /*notetypes*/];
            int            MatchingTableLength;

            /* build duration matching table */
            MatchingTableLength = 0;
            for (Scan = 0; Scan < 4 /*divisions*/ * 2 /*dot*/ * 9 /*notetypes*/; Scan += 1)
            {
                double      MIDIClocks;
                NoteFlags   Descriptor;
                FractionRec DurationFraction;

                /* determine root duration and descriptor */
                switch (Scan % 9)
                {
                default:
                    Debug.Assert(false);
                    throw new InvalidOperationException();

                case 0:
                    Descriptor = NoteFlags.e64thNote;
                    break;

                case 1:
                    Descriptor = NoteFlags.e32ndNote;
                    break;

                case 2:
                    Descriptor = NoteFlags.e16thNote;
                    break;

                case 3:
                    Descriptor = NoteFlags.e8thNote;
                    break;

                case 4:
                    Descriptor = NoteFlags.e4thNote;
                    break;

                case 5:
                    Descriptor = NoteFlags.e2ndNote;
                    break;

                case 6:
                    Descriptor = NoteFlags.eWholeNote;
                    break;

                case 7:
                    Descriptor = NoteFlags.eDoubleNote;
                    break;

                case 8:
                    Descriptor = NoteFlags.eQuadNote;
                    break;
                }

                /* determine if dot is needed */
                if (((Scan / 9) % 2) != 0)
                {
                    /* dot needed */
                    Descriptor |= NoteFlags.eDotModifier;
                }

                /* determine what division is needed */
                switch (((Scan / 9) / 2) % 4)
                {
                default:
                    Debug.Assert(false);
                    throw new InvalidOperationException();

                case 0:
                    break;

                case 1:
                    Descriptor |= NoteFlags.eDiv3Modifier;
                    break;

                case 2:
                    Descriptor |= NoteFlags.eDiv5Modifier;
                    break;

                case 3:
                    Descriptor |= NoteFlags.eDiv7Modifier;
                    break;
                }

                /* how int is this note */
                NoteNoteObjectRec.ConvertDurationFrac(Descriptor, out DurationFraction); /* units of whole notes */
                MIDIClocks = MidiQuarterNote * (4 * FractionRec.Fraction2Double(DurationFraction));

                /* add to table if note can be represented in the timing scheme */
                /* AND only if note is an integer multiple of the 64th div3 (see */
                /* comment at the top of this file for the rationale) */
                if ((MIDIClocks == Math.Floor(MIDIClocks)) && (MIDIClocks >= 1) && IntMultOf64thDiv3(Descriptor))
                {
                    MatchingTable[MatchingTableLength].Ticks      = (int)MIDIClocks;
                    MatchingTable[MatchingTableLength].Descriptor = Descriptor;
                    MatchingTableLength += 1;
                }
            }

            /* quantize note events */
            Limit = GetIntervalTrackLength(IntervalTrack);
            for (Scan = 0; Scan < Limit; Scan += 1)
            {
                IntEventRec Event;

                Event = GetIntervalTrackIndexedEvent(IntervalTrack, Scan);
                switch (IntervalEventGetType(Event))
                {
                default:
                    Debug.Assert(false);
                    throw new InvalidOperationException();

                case IntEventType.eIntervalNoteEvent:
                {
                    /* input values */
                    int   StartTime;
                    int   Duration;
                    short MIDIPitch;
                    short MIDIAttackVelocity;
                    short MIDIReleaseVelocity;
                    /* output values */
                    NoteFlags   QuantizedDuration;
                    double      QuantizedDurationAdjust;
                    int         WholeNoteOverflow;
                    FractionRec QuantizedStartTime;
                    double      QuantizedStartTimeAdjust;
                    double      WholeNoteStartTimeAdjust;    /* auxiliary value */
                    /* stuff */
                    QuantEventRec QuantEvent;

                    /* get the information */
                    GetIntervalNoteEventInfo(Event, out StartTime, out Duration, out MIDIPitch,
                                             out MIDIAttackVelocity, out MIDIReleaseVelocity);

                    /* quantize duration */
                    QuantizeDuration(Duration, MidiQuarterNote, MatchingTable,
                                     MatchingTableLength, out QuantizedDuration, out QuantizedDurationAdjust,
                                     out WholeNoteOverflow);
                    Debug.Assert(IntMultOf64thDiv3(QuantizedDuration));         // non-64div3 duration quantization?

                    /* quantize start time */
                    QuantizeStartTime(StartTime, MidiQuarterNote, QuantizedDuration,
                                      QuantizedDurationAdjust, out QuantizedStartTime, out QuantizedStartTimeAdjust,
                                      out WholeNoteStartTimeAdjust);
                    Debug.Assert(FractionIntMultOf64thDiv3(QuantizedStartTime));         // non-64div3 start time quantization?

                    /* bump start time to end of whole note chain */
                    QuantizedStartTime.Integer += (uint)WholeNoteOverflow;

                    /* create new event & insert into track */
                    QuantEvent = NewQuantizedNoteEvent(QuantizedStartTime,
                                                       QuantizedStartTimeAdjust, QuantizedDuration, QuantizedDurationAdjust,
                                                       MIDIPitch, MIDIAttackVelocity, MIDIReleaseVelocity);
                    QuantizedTrackInsertEventSorted(QuantizedTrack, QuantEvent);

                    /* insert whole notes behind the last note in reverse order */
                    while (WholeNoteOverflow > 0)
                    {
                        QuantEventRec Predecessor;

                        /* create preceding whole note */
                        QuantizedStartTime.Integer -= 1;
                        Predecessor = NewQuantizedNoteEvent(QuantizedStartTime,
                                                            WholeNoteStartTimeAdjust, NoteFlags.eWholeNote, 1, MIDIPitch,
                                                            MIDIAttackVelocity, MIDIReleaseVelocity);
                        QuantizedTrackInsertEventSorted(QuantizedTrack, Predecessor);
                        /* set tie */
                        PutQuantizedEventTieTarget(Predecessor, QuantEvent);
                        QuantEvent = Predecessor;
                        /* step */
                        WholeNoteOverflow -= 1;
                    }
                }
                break;

                case IntEventType.eIntervalCommentEvent:
                {
                    QuantEventRec QuantEvent;
                    /* input values */
                    int    StartTime;
                    string OriginalString;
                    /* output values */
                    FractionRec QuantizedStartTime;

                    /* get the information */
                    GetIntervalCommentEventInfo(Event, out StartTime, out OriginalString);

                    /* compute start time to nearest 64th div3 */
                    FractionRec.Double2Fraction(StartTime / (double)MidiQuarterNote,
                                                64 * 3, out QuantizedStartTime);
                    Debug.Assert(FractionIntMultOf64thDiv3(QuantizedStartTime));         //non-64div3 start time quantization?

                    /* create new event & insert into track */
                    QuantEvent = NewQuantizedCommentEvent(QuantizedStartTime, 0, OriginalString);
                    QuantizedTrackInsertEventSorted(QuantizedTrack, QuantEvent);
                }
                break;
                }
            }

            return(true);
        }