; ------------------------------------------------------------------------------------------------- ; Keep Top of Chord.cal ; ------------------------------------------------------------------------------------------------- ; ; Author: Eric von Bayer ; Email: CAL @ ericvonbayer.us (remove the spaces) ; WWW: http://www.ericvonbayer.us ; Dates: January 2005 - January 2005 ; Version: 1.2 ; Description: ; ; Simple script to keep the bottom note of a chord, a chord is denoted as a set of notes ; that start at the same time (not necessarily are playing at the same time) ; ; ------------------------------------------------------------------------------------------------- ; Make Sure we're new enough ; ------------------------------------------------------------------------------------------------- (do (if (< VERSION 40) (do (pause "This CAL program requires CAL version 4.0 or higher") (exit) ) ) ; ------------------------------------------------------------------------------------------------- ; Config Section ; ------------------------------------------------------------------------------------------------- (word wNoteDur 16) ; Duration of note to tolerate as being the same (16th Note) ; ------------------------------------------------------------------------------------------------- ; Main processing loop ; ------------------------------------------------------------------------------------------------- (dword dInitTime -999999) (dword dLastTime dInitTime) (int iLastChan 0) (int iLastKey 0) (int iLastVel 0) (dword dLastEnd 0) (dword dTmpEnd 0) ; Calculate the tolerance (dword dTicksTol (/ (* TIMEBASE 4) wNoteDur ) ) ; Get the last index (dword dLastIndex 0) (dword dCountIndex 0) (forEachEvent (= dLastIndex (index) ) ) (forEachEvent (do ; Only process notes (if (== Event.Kind NOTE) (do ; Calculate the note end (= dTmpEnd (+ Event.Time Note.Dur ) ) ; See if we don't match the last time (if (|| (<= (+ dLastTime dTicksTol ) Event.Time ) (== dLastTime dInitTime) ) (do ; Make sure we're not the first event (if (!= dLastTime dInitTime) (do (insert dLastTime iLastChan NOTE iLastKey iLastVel (- dLastEnd dLastTime) ) ) ) ; Update the info for a new note (= dLastTime Event.Time) (= iLastChan Event.Chan) (= iLastKey Note.Key) (= iLastVel Note.Vel) (= dLastEnd dTmpEnd) ) (do ; We match the last time ; Are we a higher key? (if (> Note.Key iLastKey ) (do ; Save the new information (= iLastChan Event.Chan) (= iLastKey Note.Key) (= iLastVel Note.Vel) ) ) ; If the end point is later, adjust the stored one (if (> dTmpEnd dLastEnd ) (do (= dLastEnd dTmpEnd) ) ) ) ) ; Delete the note regardless (delete) ) ) ; If we have an event and we're on the last event, write it out (if (&& (== dCountIndex dLastIndex ) (!= dLastTime dInitTime) ) (do (insert dLastTime iLastChan NOTE iLastKey iLastVel (- dLastEnd dLastTime) ) ) ) ; Increment the index counter (++ dCountIndex) ) ) )