In order to edit an event, you must first make it the currently selected event,. A newly inserted event automatically becomes the currently selected event. Alternately, an event enumerated by MIDIGetEvent() also becomes the currently selected event.

To edit the event, you merely set the same variables that MIDIGetEvent() would set, and then call MIDISetEvent().

The event's TIME is set by the variables MIDIEvent.!Measure, MIDIEvent.!Beat, and MIDIEvent.!Clock.

If the event has a channel, that is set by the variable MIDIEvent.!Channel.

The variables you set to change the event's data, and what values you set them to, depends upon the type of event.

After you set the above variables, then you can call MIDISetEvent(). Note that if you call MIDIGetEvent() to enumerate an event, MIDIGetEvent() will have set all of those variables to whatever values the event currently has. So, you need set only those variables that you desire changed.

For example, here we enumerate any On Note events in track 10, and change the velocity to 127:

/* Set only track 10 as searchable */
selected = MIDITrack(10)

/* If it has data... */
IF selected \== 0 THEN DO

   /* Keep going until an error */
   DO UNTIL err \== ""

      /* Enumerate the next On Note event */
      err = MIDIGetEvent('On Note')

      /* If there's another event, set its velocity */
      IF err == "" THEN DO

         MIDIEvent.!Data2 = 127	  
         err = MIDISetEvent()
	     IF err \== "" THEN SAY "ERROR: " err

      END

      /* If the error message indicated something
       * other than no more events, display it
       */
      ELSE IF err \== "No currently selected event" THEN SAY "ERROR:" err

   END

END
If you wish to set the event's TIME, channel, or data, but not all three components, you can specify which component you want to set. MIDISetEvent() will set only that component, and not the others. For example, here we specify that MIDISetEvent() is to set only the event's data, and not its TIME nor channel.
/* Set only track 10 as searchable */
selected = MIDITrack(10)

/* If it has data... */
IF selected \== 0 THEN DO

   /* Keep going until an error */
   DO UNTIL err \== ""

      /* Enumerate the next On Note event */
      err = MIDIGetEvent('On Note')

      /* If there's another event, set its velocity */
      IF err == "" THEN DO

         MIDIEvent.!Data2 = 127	  
         err == MIDISetEvent('DATA')
         IF err \== "" THEN SAY "ERROR: " err

      END

      /* If the error message indicated something
       * other than no more events, display it
       */
      ELSE IF err \== "No currently selected event" THEN SAY "ERROR:" err

   END

END
The above two examples achieve the same things, since MIDIGetEvent() sets the variables MIDIEvent.!Measure, MIDIEvent.!Beat, MIDIEvent.!Clock, and MIDIEvent.!Channel anyway. But the second example is faster since MIDISetEvent() doesn't bother setting the TIME or channel when it's not necessary (because we didn't change those variables).

You can set only the time by specifying 'TIME', and setting only the MIDIEvent.!Measure, MIDIEvent.!Beat, and MIDIEvent.!Clock variables. For example, to set the event to play on the 30th clock after the second downbeat in the third measure:

MIDIEvent.!Measure = 3
MIDIEvent.!Beat = 2
MIDIEvent.!Clock = 30
err = MIDISetEvent('TIME')
You can set only the channel by specifying 'CHAN', and setting only the MIDIEvent.!Channel variable. For example, to set the event to play on MIDI channel 10:
MIDIEvent.!Channel = 10
err = MIDISetEvent('CHAN')
You can also combine the components by separating them with a '|' character. Here we set the channel and data for our On Note event (but not the TIME):
/* Change to channel 10 */
MIDIEvent.!Channel = 10
/* Change to note number 60 */
MIDIEvent.!Data1 = 60
/* Change to velocity of 127 */
MIDIEvent.!Data2 = 127
err = MIDISetEvent('CHAN|DATA')
Some events have several data fields. For example, an On Note event has both a note number (set via MIDIEvent.!Data1) and a velocity (set via MIDIEvent.!Data2). If you wish to set only one of those two fields, then set its variable. For the other field, set its variable to an empty string, and MIDISetEvent() will not change that field. For example, here we set the On Note's velocity, but don't change its note number:
/* Don't change the note number */
MIDIEvent.!Data1 = ""
/* Change to velocity of 127 */
MIDIEvent.!Data2 = 127
err = MIDISetEvent('DATA')
For some events, the data fields duplicate the same information. For example, a Tempo event has both a Micros per Quarter note (set via MIDIEvent.!Data1) and a BPM (set via MIDIEvent.!Data2). Both of these fields express the same information, but in a different way. In this case, if you set both variables, MIDISetEvent() recognizes only the first field (ie, micros). In order to set the Tempo by BPM, you must set MIDIEvent.!Data1 to an empty string, as so
/* Ignore micros per quarter */
MIDIEvent.!Data1 = ""
/* Set Tempo BPM to 100 */
MIDIEvent.!Data2 = 100
err = MIDISetEvent('DATA')
Likewise, if you set a Pitch Wheel's range, or a Sng Position, or a Key Sig, via MIDIEvent.!Data3, then MIDIEvent.!Data1 and MIDIEvent.!Data2 are ignored.

One discrepancy between MIDIGetEvent() and MIDISetEvent() concerns Sysex (as well as First Packet/Packet/Last Packet) events. MIDIGetEvent() sets MIDIEvent.!Data1 to the size of the Sysex data. But when editing the event via MIDISetEvent(), you set MIDIEvent.!Data1 to the actual Sysex data. You can use D2C() if you specify the Sysex bytes as numeric strings. Or, you can specify the bytes verbatim by using a hexadecimal literal string.