Jump to content

I need help writing a CAL script for moving MIDI notes


Recommended Posts

Hi everyone 👋 I need help with writing a CAL script which moves all the notes in one MIDI track to 6 other MIDI tracks. I need all C's and C#'s to be moved to track 2, all D's and D#'s to be moved to track 3, all E's and B's to be moved to track 4, all F's and F#'s to be moved to track 5, all G's and G#'s to be moved to track 6, and all A's and A#'s to be moved to track 7. I'm trying to create a rainbow color theme for MIDI files in Synthesia to enhance the user's sightreading ability. I asked ChatGPT to write the CAL script but it failed over and over again. It kept getting errors like "CAL Error 004: Unknown Procedure and" and "CAL Error 003: Wrong number of arguments if". Is there a way to do this with CAL?

Here's the first script it gave me:

(do
  (include "need20.cal") ; Ensure we're running in CAL 2.0 or later.

  (int i) ; Counter for iteration
  
  ; Iterate over all selected events in track 1.
  (forEachEvent
    (if (and (== Event.Kind NOTE) 
             (or (== Event.Track 1))) ; Only consider notes from track 1
      (begin
        ; Move C notes (MIDI note numbers 0, 12, 24, ...) to track 2
        (if (== (mod Event.Note 12) 0)
          (setEvent Track 2)
        )
        ; Move C# notes (MIDI note numbers 1, 13, 25, ...) to track 2
        (if (== (mod Event.Note 12) 1)
          (setEvent Track 2)
        )
        ; Move D notes (MIDI note numbers 2, 14, 26, ...) to track 3
        (if (== (mod Event.Note 12) 2)
          (setEvent Track 3)
        )
        ; Move D# notes (MIDI note numbers 3, 15, 27, ...) to track 3
        (if (== (mod Event.Note 12) 3)
          (setEvent Track 3)
        )
        ; Move E notes (MIDI note numbers 4, 16, 28, ...) to track 4
        (if (== (mod Event.Note 12) 4)
          (setEvent Track 4)
        )
        ; Move B notes (MIDI note numbers 11, 23, 35, ...) to track 4
        (if (== (mod Event.Note 12) 11)
          (setEvent Track 4)
        )
        ; Move F notes (MIDI note numbers 5, 17, 29, ...) to track 5
        (if (== (mod Event.Note 12) 5)
          (setEvent Track 5)
        )
        ; Move F# notes (MIDI note numbers 6, 18, 30, ...) to track 5
        (if (== (mod Event.Note 12) 6)
          (setEvent Track 5)
        )
        ; Move G notes (MIDI note numbers 7, 19, 31, ...) to track 6
        (if (== (mod Event.Note 12) 7)
          (setEvent Track 6)
        )
        ; Move G# notes (MIDI note numbers 8, 20, 32, ...) to track 6
        (if (== (mod Event.Note 12) 😎
          (setEvent Track 6)
        )
        ; Move A notes (MIDI note numbers 9, 21, 33, ...) to track 7
        (if (== (mod Event.Note 12) 9)
          (setEvent Track 7)
        )
        ; Move A# notes (MIDI note numbers 10, 22, 34, ...) to track 7
        (if (== (mod Event.Note 12) 10)
          (setEvent Track 7)
        )
      )
    )
  )
)

Does anyone know how to do this properly?

Thanks!

Link to comment
Share on other sites

  • 1 month later...

Hi:)

 

In "*\Cakewalk Content\Sonar\CAL Scripts" is a script which splits notes to tracks, I attached the file, but here's the script itself:

;
; Split Note to Tracks.cal
;
; This routine modifies a source track, splitting it by note# into 
; separate destination tracks. Only notes are split ... all other 
; track parameters (Controllers, Tempos, Meters and Markers), 
; if any, remain in the source track.
;
; Use this routine for splitting up a drum machine or other type 
; of instrument track where voices are assigned by note number.
;
; = Courtesy Red Nile Productions 1993 (714)498-7515 CIS:70044,2733
;
; = Modified 12/10/93 by Greg Hendershott at user's request to
;   have this display notes as names (like C#5) rather than numbers
;   in the track names.  Caveat: The note names always use sharps
;   and assume BaseOctave=0.

(do
	(if (< VERSION 20)
		(do
			(pause "This CAL program requires CAL version 2.0 or higher")
			(exit)
		)
	)
	(include "need20.cal")	; Require version 2.0 or higher of CAL

	(int nOctave)
	(int nSrcTrk 1)
	(int nDestTrk (+ nSrcTrk 1))
	(int nDestChan 0)
	(int nDestPort 1)
	(int nNote 0)
	(int bEvent FALSE)

	(getInt nSrcTrk "Source Track?" 1 256)
	(-- nSrcTrk)	; CAL uses 0..255

	(getInt nDestTrk "First Destination Track?" 1 256)
	(-- nDestTrk)	; CAL uses 0..255

	(getInt nDestChan "Destination Channel?" 0 16)
	(-- nDestChan)	; CAL uses -1..15

	(getInt nDestPort "Destination Port?" 1 16)
	(-- nDestPort)	; 0 .. 15

	; If markers not set, select entire range
	(if (== From Thru) 
		(do
			(= From 0)
			(= Thru End)
		)
	)

	; Select only source track
	(TrackSelect 0 -1)
	(TrackSelect 1 nSrcTrk)

	; Set filter params. Split notes only .. 
	; Controllers stay in source track.
	(ResetFilter 0 TRUE)
	(SetFilterKind 0 NOTE TRUE)
	(SetFilterKind 0 KEYAFT FALSE)
	(SetFilterKind 0 CONTROL FALSE)
	(SetFilterKind 0 PATCH FALSE)
	(SetFilterKind 0 CHANAFT FALSE)
	(SetFilterKind 0 WHEEL FALSE)
	
	(while (< nNote 127)
		(do
			; Check for note events at current note # ...
			(forEachEvent
				(if (&& (== Event.Kind NOTE) (== Note.Key nNote))
					(= bEvent TRUE)
				)
			)

			; If there are note events, paste them to the destination track
			(if (== bEvent TRUE)
				(do
					; Status message
					(message "Note # " nNote " --> Track " (+ 1 nDestTrk))

					; Set up filter .. item 0, NOTE, in the range nNote..nNote
					(SetFilterRange 0 0 TRUE nNote nNote)
					
					; Cut/Paste the filtered events to the destintation track
					(EditCut From Thru TRUE TRUE FALSE FALSE FALSE FALSE)
					(EditPasteToTrack From 1 1 TRUE FALSE FALSE FALSE nDestTrk)

					; Name dest track
					(= nOctave (/ nNote 12))
					(switch (% nNote 12)
						0 (TrackName (format "Split Note C" nOctave) nDestTrk)
						1 (TrackName (format "Split Note C#" nOctave) nDestTrk)
						2 (TrackName (format "Split Note D" nOctave) nDestTrk)
						3 (TrackName (format "Split Note D#" nOctave) nDestTrk)
						4 (TrackName (format "Split Note E" nOctave) nDestTrk)
						5 (TrackName (format "Split Note F" nOctave) nDestTrk)
						6 (TrackName (format "Split Note F#" nOctave) nDestTrk)
						7 (TrackName (format "Split Note G" nOctave) nDestTrk)
						8 (TrackName (format "Split Note G#" nOctave) nDestTrk)
						9 (TrackName (format "Split Note A" nOctave) nDestTrk)
						10 (TrackName (format "Split Note A#" nOctave) nDestTrk)
						11 (TrackName (format "Split Note B" nOctave) nDestTrk)
					)
					
					; Set forced channel & port, and unmute it
					(TrackChannel nDestChan nDestTrk)
					(TrackPort nDestPort nDestTrk)
					(TrackActive TRUE nDestTrk)
					
					(++ nDestTrk)
					(= bEvent FALSE)
				)
			)
			; Else
			(++ nNote)
		)
	)
)

Greetz;)

Bassman.

 

Split Note to Tracks.cal

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...