Jump to content

CAL Script - Remove Voices


Recommended Posts

Hi all,

I'm looking for a script that would allow me to remove the first or second voice of a melodic line while keeping the unison parts.

Is this possible?

For example, when the flutes play together, nothing is deleted, but when they split, I would like to be able to remove the top or bottom line.

Best

Link to comment
Share on other sites

When you say "unison", do you mean voices on the same pitch or an octave apart? Either way, the two voices would first need to be combined in a single MIDI clip (with events on different channels if they're on the same pitch). Then it would be possible to write a CAL to do that but I don't know of one that exists, and it wouldn't be trivial enough for me to want to try it for fun. ;^)

Do you run into this situation enough to justify needing a script for it? I would think it's not that difficult to do manually in the PRV with the two voices in separate tracks.

 

Link to comment
Share on other sites

By "unison," I indeed mean the same pitch. I often import MIDI files from a notation software where two instruments are on the same track 12.png.2fea399c4bc273c9b3eaf2b211232180.png.

A script like this would allow me to quickly delete the top line for the entirety of Track 1

1.png.efbec82665307948f9a8d704b46d12e6.png

And the bottom line for Track 2. That’s all I need—nothing more  :)

2.png.61c72e584293ada4189b3a8493c37e4d.png

 

Without even needing to separate them into two tracks

Link to comment
Share on other sites

I have tried similar, but it is not easy. With this particular example you can delete the top instrument, except for notes that both play. That just leaves a few to delete manually. And ditto for the bottom octave.

And in future don't put 2 instruments on the same track in the notation software

With CAL the track can be scanned and if there are 2 notes the top(bottom) one can be deleted. But they would have to start at the exact same time. Down to ticks.

  • Great Idea 1
Link to comment
Share on other sites

On 11/21/2024 at 1:13 AM, Nigel Mackay said:

And in future don't put 2 instruments on the same track in the notation software

The correct answer.

Foresight eliminates many problems before they begin.  I have found that a lot of times a little bit more time on the front end of a task saves a whole lot on the back end.

  • Great Idea 1
Link to comment
Share on other sites

Salut Mathieu,

Si ma mémoire est bonne j'ai pu programmer une routine fiable. Ça ne coûte rien d'essayer, copie le tout dans un fichier et sauve le sous Note_Duplicate.CAL par exemple.

;; _54 Note_Duplicate.CAL, by Serge Daigno 2022

;; Delete duplicated notes junk
;; If many tracks are selected, results are not guaranteed

(do
  (dword FromTime 0) (word oRange 50)
  (int NoteKey 0) (int nDeleted 0) (int nDuration 0)
  (int Found 0)
  (int FromKey 32767) (int ToKey 0)            ; Key range
  (int oCh 0) (int oVel 10) (int oNote 0) (word oDur 30)     ; Data insert

  (getWord oRange "Relative time range in Ticks:" 0 100)
  (getInt oVel "Delete Velocity lower than:" 1 20)
  (getInt oDur "Delete Duration lower than:" 1 50)

; -------------  First of all, delete duration and velocity junk, get the lowest and highest notes.

  (forEachEvent  
  (do    ; Find note range

     (if (== Event.Kind NOTE)
     (do
        (++ Found)
        (if (&& (== Event.Kind NOTE) (< Note.Dur oDur)) (do (delete) (++ nDeleted))) ;; Junk
        (if (&& (== Event.Kind NOTE) (< Note.Vel oVel)) (do (delete) (++ nDeleted))) ;; Junk
        (if (< Note.Key FromKey) (= FromKey Note.Key))
        (if (> Note.Key ToKey) (= ToKey Note.Key))
     ))
  ))
  (= oVel 0) (= oDur 0)

  (while (<= FromKey ToKey)
  (do
; -------------  Remove duplicates

        (= Found 0)     
        (forEachEvent   
        (do
            (if (&& (== Found 1) (&& (== Event.Kind NOTE) (== Note.Key FromKey))) ; Next FromKey
            (do
               (if (&& (>= Event.Time FromTime) (<= Event.Time (+ FromTime oRange))) (do (delete) (++ nDeleted)))
               (if (> Event.Time (+ FromTime oRange)) (= Found 0)) ; Out of range
            ))

            (if (&& (== Found 0)  (&& (== Event.Kind NOTE) (== Note.Key FromKey))) ; FromKey
            (do
               (= FromTime Event.Time) (= Found 1) ; To next FromKey
            ))
        ))

; -------------  Remove overlaps

        (= Found 0)     
        (forEachEvent   
        (do
            (if (&& (== Found 1) (&& (== Event.Kind NOTE) (== Note.Key FromKey))) ; FromKey found
            (do
              (if (> oDur (- Event.Time FromTime )) (do (= oDur (- Event.Time FromTime )) (++ nDuration)))
              (insert FromTime oCh NOTE FromKey oVel oDur) (= Found 0)
              ;(pause "Ev " Event.Time " Fr: " FromTime " Dur: " oDur)
            ))

            (if (&& (== Found 0)  (&& (== Event.Kind NOTE) (== Note.Key FromKey))) ; FromKey
            (do
               (= FromTime Event.Time) (= Found 1) ;(pause "0 Key: " FromKey " Time: " FromTime)
       (= oCh Event.Chan) (= oNote Note.Key) (= oVel Note.Vel) (= oDur Note.Dur) (delete)  ; Store values
             ))
        ))
        (if (== Found 1) (insert FromTime oCh NOTE FromKey oVel oDur)) ; Last FromKey performed
        (++ FromKey)
  ))
  (pause "Duplicates " nDeleted " Overlaps: " nDuration)
)

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...