Before we start down the road to writing custom editing functions, we should take a look at how the sequence data is formatted and stored in a computer so we have a better idea just what can and can't be done to it using CAL. First, it is important to realize that the sequences are organized by event times and also by track. That is, in the sequence file, all events that take place on the same track need to be kept together and in order by event time regardless of what MIDI channel they are set to broadcast over. As a result, if you ask an editing feature to operate on events from time X to time Y on tracks A B and C, the software should start at time X and work on all of the events on track A until it reaches the last event at time Y. It should then start over at time X on track B and do the same thing. It does this in one long pass, first one track and then the next. If you build a CAL program that must keep the events on each track separate, you can depend on CAL to operate only on the events in one track from the starting time at the "From" marker to the end time at the "Thru" marker before going on to the next track.
The reason I said "should" in the paragraph above is due to the habit later versions of Cakewalk (that use the concept of "clips" within a track) have of getting sequences in a track "out of sequence". To explain, take this example. Suppose you have a track that you want to split up into several tracks. Now let's say that you cut some events out of the first track and paste them to a new track. Later, you cut some more events and add them to that new track as a separate but overlapping clip. Perhaps after doing just this much editing to the new track, or maybe after a few more such clip paste additions, the events will no longer be in the order in which they will play. The events from the first clip will start at the head of the track and run to the last event from that clip, and then will start the events from another pasted clip and run to the last of that group of events. The result will be a track that has several starting points, each with a group of events running from a start to an end. There will be no change in the way the events are played back or, with the exception of the occasional bug, in the way they are displayed. As far as anyone can tell, all of the events have been properly integrated and they exist on the track in the order in which they will play regardless of how many edits it took to put them all there or how many clips overlap. The problem comes when CAL attempts to work on such a track. If the CAL program depends on the events being in the same order on the track as the order in which they will play, say because it has to calculate the gap between notes and their neighboring notes in order to decide if a given note qualifies for some action or another, then the notes being out of order will cause the CAL program to malfunction - BADLY!
Apparently what happens here is that Cakewalk is able to build "sub-tracks" out of clips within a track the same way it builds tracks within a sequence. In the sequence, each track starts at some point in memory, runs its length and then ends. The next track's contents follows the first, then the next track and so on. If, before running a CAL program, you select more than one track, CAL will act on all of the events in the first track from start to finish and then go the next track and work on it from start to finish. This is in spite of the fact that when a sequence plays, Cakewalk plays all tracks at the same time regardless of where those tracks start and end in memory. CAL does not! If some editing function or group of functions cause Cakewalk to overlap clips in the same track, each with its own starting and ending point in memory, then CAL can't operate on it as a unified track with one starting point, one ending point and all of the events in proper order within. The best answer is to make sure when you paste a new clip to a track that you select "Paste Into Existing Clip" instead of "Paste As New Clip" from the PASTE dialog. However, if the damage is already done, there is a fix. If you look at the sample CAL programs included with this document, you will see there is an "include" program called TIMERROR.CAL being called at the start of any program that is sensitive to the proper ordering of events on a track. This included program scans the selected track and tests the event times of all of the events. If it finds that they are out of order, it issues a warning message and causes CAL to abort. For a way around this condition, see the section called Tips, Techniques and Work-Arounds under the sub-heading Correcting Sequences That Aren't Sequential for the details.
Another fact to remember is that if you assign a MIDI channel to a track, events on that track will be broadcast over that channel even if the event has a different channel assignment within its data pattern. This is why you can bounce events from track 2 on channel 2 to track 4 on channel 4 and have them all go out on channel 4. You can see this oddity if you examine a track by selecting the EVENT LIST VIEW and look at events that were bounced from another track. They will likely be allocated to a different channel than the events native to the track. However, all of them will output to the channel for that track providing one has been selected. If you were to select 0 for the track channel, then the events would be broadcast on whatever channel their event data says. This is good to know because events on a track can be segregated for editing by changing their MIDI channel without really changing the channel they will be broadcast to. This will become clearer if you look at a sample CAL program called CROSFADE.CAL that selectively inserts events of differing channel assignments and then later uses this distinction to edit them. It is also critical you be aware that even though we call the MIDI channels 1 through 16, CAL calls them channels 0 through 15.
Time in a sequence is different than the time you see on the screen. In a sequence, time is a raw number of clock ticks stored as a double word (32 bit value) from 0 to 4.29 billion whereas on the screen it is displayed as measures, beats and ticks or M:B:T time. The raw time is converted to M:B:T time according to the value stored in TIMEBASE in the SETTINGS menu (in version 7, from the TOOLS menu, select the "Project Options" heading, then the CLOCK tab) and the number of beats per measure. For normal settings of 120 ticks per quarter note and a meter of 4/4, there are 480 ticks per measure. CAL has functions that can convert the raw time and M:B:T time back and forth taking your settings into account.
Although it may not seem important on the surface, different events have different amounts of data associated with them. While all events have a time at which they are to be broadcast and a channel they are set to broadcast over, note events will also have a pitch, velocity and duration as part of their data content or a controller event will have a controller number and a controller value. All data associated with an event will be referred to as one or more of its "variables" (remember your algebra?) because these values can be read and changed in the editing process. When writing CAL programs, one of the easiest mistakes to make is to forget what event type has what kinds of variables.
Here is an odd point. A note event has a duration variable associated with it. As a result, when the note is sent over MIDI, a "NOTE ON" command will be sent at the time of the note, and a separate "NOTE OFF" command (usually another NOTE ON command but with a velocity of 0) is sent after the duration time has elapsed. So even though the note is displayed as one event in the sequence, it results in the broadcasting of two separate MIDI commands in order to satisfy its purpose. If you have ever "pasted with replace" a measure over a note that extended from the previous measure into the one being pasted over, you may have experienced a stuck note due to the confusion that can be caused by overwriting a sustained note's OFF location.