Function summary | |
---|---|
corresponding-rest | event |
filter-notes-if | test omn &key (remain t) (section nil) |
insert-articulation | flat-omn-list &rest articulations |
remove-unless-parameters | flat-omn-list parameter &key (remove-non-matching? nil) |
separate-parts | sequence articulation-sets |
_push-event-and-rests | event matching-position result-omns articulation-sets-length |
Extracts events in OMN for which a given test function returns true (or keeps only events for which the test function returns nils). All other notes are turned into rests.
test: Boolean function expecting individual parameters of each note in `OMN'
OMN: An OMN sequence
remain: Boolean expressing whether only matching notes (T) or non-matching notes (nil) should be kept.
section: an integer or list of integers. Selected list or lists to process. The default is NIL.
See also Opusmodus builtin `filter-events'.
Keep only notes above middle C and turn other notes into rests
(filter-notes-if #'(lambda (dur pitch &rest other-args) (> (pitch-to-midi pitch) 60)) '(e c4 mp -e fermata e. d4 -h e. c4 e e4))
Do the opposite with :remain nil.
(filter-notes-if #'(lambda (dur pitch &rest other-args) (> (pitch-to-midi pitch) 60)) '(e c4 mp -e fermata e. d4 -h e. c4 e e4) :remain nil)
This also works with nested lists and you can process only selected bars (other bars are kept unchanged).
(filter-notes-if #'(lambda (dur pitch &rest other-args) (> (pitch-to-midi pitch) 60)) '((e c4 mp -e fermata e. d4 -s) (-q.. e. c4 e e4)) :section 1)
For musical application examples see also {https://opusmodus.com/forums/topic/867-opusmodus-1222292/}.
This function could also be useful for Beethoven like motif condensation, where notes are first turned into rests with this function, and then their preceding notes are extended with length-legato, as demonstrated in the following example.
(setf my-motif '((q. c4 e d4 q. e4 e f4) (h g4 -h))) (length-legato (filter-notes-if #'(lambda (dur pitch &rest other-args) (> (omn-encode dur) 1/4)) my-motif)) => ((h c4 e4) (w g4))
https://opusmodus.com/forums/topic/910-merge-rests-with-preceeding-note/?tab=comments#comment-2713
Turns a single OMN note into a rest of the same note value. Rests remain rests, and rest articulations are preserved.
(corresponding-rest '(h c4))
The function `separate-parts' is useful for customising your sound playback with multiple sound libraries or for algorithmic orchestration. The function breaks an OMN sequence (a single part) into a list of multiple OMN sequences (multiple parts). It basically sorts notes from the OMN sequence into different parts, depending on the articulations of individual notes. All notes with certain articulations go in one resulting parts, and notes with other articulations in another part. In all other resulting parts, notes are substituted by rests, so that timing relations of notes in different parts are preserved. This function can be useful, when you have multiple sound libraries that support different articulations of the same instrument. You can then perform notes with certain articulations on one software instrument (on its own MIDI channel etc.), and notes with other articulations on another instrument. Alternatively, you can use the function for algorithmic orchestration, where you assign custom articulations (typically declared with add-text-attributes first) such as instrument labels with your custom algorithm, and then use this function in a second step to separate your instruments.
Remember that the result of this function is a list of multiple OMN sequences (multiple parts). You have to split it into its individual parts for use in OMN.
See also {https://opusmodus.com/forums/topic/849-towards-algorithmic-orchestration-and-customising-sound-playback-with-multiple-sound-libraries/}
sequence: OMN sequence, can be nested
articulation-sets: list of list of articulations. All notes with articulations contained in the first articulation-set end up in the first resulting part, notes with articulations in the second set end up in the second part and so forth. The decision which part a note belongs to is always made based on the first articulation that matches an articulation-set. If a note contains no articulation, or an articulation contained in no set, then it is matched to the first articulation-set. If an articulation is contained in multiple articulation-sets, then the earlier match in articulation-sets is used.
(separate-parts '(h c4 pizz q arco) '((pizz) (arco))) => ((h c4 mf pizz -q) ; part 1 with pizz articulations (-h q c4 mf arco)) ; part 2 with arco
(separate-parts '((h c4 pizz q arco) (h trem q h pizz) (h arco+stacc -q fermata)) '((pizz arco) (trem))) => (((h c4 mf pizz q arco) (-h q c4 mf h pizz) (h c4 mf arco+stacc -q fermata)) ; part 1: pizz and arco ((-h -q) (h c4 mf trem -q -h) (-h -q fermata))) ; part 2: trem
Full score example:
(setf omn-expr '((h c4 pizz q arco) (h trem q h pizz) (h arco+stacc -q fermata))) (setf parts (separate-parts omn-expr '((pizz arco) (trem)))) (def-score two-violins (:title "Title" :composer "Composer" :copyright "Copyright © " :key-signature 'chromatic :time-signature '((1 1 1 1) 4) :tempo 100 :layout (bracket-group (violin1-layout 'violin1) (violin2-layout 'violin2))) (violin1 :omn (nth 0 parts) :channel 1 :sound 'gm :program 'violin :volume 100 :pan 54 :controllers (91 '(48)) ) (violin2 :omn (nth 1 parts) :channel 2 :sound 'gm :program 'violin :volume 100 :pan 74 :controllers (91 '(60)) ) )
Merge in one or more lists of articulations to an OMN expression.
added nil for the rest
(insert-articulation '(e c4 mp arco e. d4 -h e. p pizz e e4 arco) '(ponte tasto nil ponte tasto)) => (e c4 mp arco+ponte e. d4 mp tasto -h e. d4 p pizz+ponte e e4 p arco+tasto)
BUG: does not skip rests. Wait for omn-replace supports composite articulations to fix
Checks every note whether it contains `parameter'. All notes containing the parameter are preserved, all other notes are turned into rests. If a note contains a combination of articulations, all of them are checked.
flat-omn-list: flat OMN list
parameter: a length, pitch, OMN velocity or single articulation
remove-rests? (default nil): if true, all notes that do not match are removed instead of turned into rests.
(remove-unless-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'e.) => (-1/8 e. d4 mp tasto -1/2 e. c4 p pizz+ponte -1/8)
(remove-unless-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'arco) => (e c4 mp arco+ponte -3/16 -1/2 -3/16 e e4 p arco+tasto)
(remove-unless-parameters '(e c4 mp arco+ponte e. d4 mp tasto -h e. c4 p pizz+ponte e e4 p arco+tasto) 'arco :remove-non-matching? T) => (e c4 mp arco+ponte e e4 p arco+tasto)