score

Function summary
append-scores &rest scores
apply-part instrument score fn args &key (parameter nil)
extract-parts instruments score
generate-parts fn part-args &key (shared-args nil)
get-instruments score
get-part-omn instrument score
get-parts-omn score
map-parts score fn part-args &key (parameter nil) (input-parameter nil) (output-parameter nil) (shared-args nil) (flatten nil) (swallow nil)
map-parts-equally score fn args &key parameter skip
merge-equal-instrument-parts score
merge-voices2 seq insert bar/beat
mix-scores &rest scores
preview-score score &key (name 'test-score) (instruments *default-preview-score-instruments*) (header *default-preview-score-header*)
remove-part instrument score
remove-parts instruments score
reorder-parts instruments-in-order score
replace-instruments new old score
replace-part-omn instrument new-part score
score-duration score
split-part instrument orig-score score-to-insert
split-score-at-bar-boundaries score &optional positions
split-score-at-shared-rests score
unify-part-durations score
unify-time-signature instrument-with-time-signature score
_append-two-parts score1 score2
*default-preview-score-instruments*    [Variable]

Settings for each instrument used by `preview-score'. The format is a plist where keys are the instrument labels, and values a list with the actual settings. For format of these settings are the same as instrument settings for `def-score' with keywords like :sound, :channel etc. -- except for they key :omn.

*default-preview-score-header*    [Variable]

Global score settings used by `preview-score'. The format is a plist where keys are the instrument labels, and values a list with the actual settings. The format is the same as the header settings for `def-score' with keywords like :title, :key-signature etc.

*preview-score-return-value*    [Variable]

Controls the return value of function preview-score.

Possible values are

  • :headerless-score - the input score to preview-score

  • :full-score - the full def-score expression generated

  • :score - the resulting score object

preview-score   score &key (name 'test-score) (instruments *default-preview-score-instruments*) (header *default-preview-score-header*)  [Function]

Notates and plays a score in a format slightly simpler than expected by def-score, i.e., without its header. Args:

  • score (plist): a headerless score. See below for its format.

  • name (symbol): The score name.

  • instruments (plist): Keys are instrument labels, and values a list with the actual settings. These settings have the same format as instrument settings for `def-score' with keywords like :sound, :channel etc. -- except for they key :omn. This list can contain more instruments than actually contained in score (e.g., settings for a full orchestra), but only the instruments actually contained in `score' are actually given to the internal `def-score' call.

  • header (plist): The format is the same as the header settings for `def-score' with keywords like :title, :composer, :key-signature etc. Note: any time signature sequence given in the `header' that is not long enough for the full score is automatically cycled as a sequence to the required length (i.e., not only the last time signature but the whole sequence is repeated).

Score format:

    (<part1-name-keyword> <part1-OMN> 
      <part2-name-keyword> <part2-OMN> 
      ...)  

Examples:

Example using the two default instrument names, predefined with `*default-preview-score-instruments*' and `*default-preview-score-header*'.

    (preview-score 
      '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) 
        :vlc ((q g3) (q c4 b3 a3 g3) (h. c3)))) 

Example showing how to define your own instrument specifications. These specifications can either be directly handed to preview-score, as shown below, or you can overwrite `*default-preview-score-instruments*' and `*default-preview-score-header*' accordingly. NOTE: when specifying the score :layout as header argument, list instrument names as symbols in the Opusmodus package and *not* keywords as in the headerless score. See the example below.

    (preview-score 
      '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) 
        :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) 
      :instruments '(:vln (:program 'violin :sound 'gm) 
     		    :vlc (:program 'cello :sound 'gm)) 
      :header `(:layout (,(bracket-group (violin-layout 'vln) 
                                         (violoncello-layout 'vlc))))) 

The return value is controlled by *preview-score-return-value*

Polyphonic parts can be expressed by simply using the same instrument name multiple times (again using default instrument names).

    (preview-score 
      '(:vln ((q g5) (q. c6 e d6 q e6 f6) (h. e6)) ; octave-doubling 
        :vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5))  
        :vlc ((q g3) (q c4 b3 a3 g3) (h. c3)))) 

generate-parts   fn part-args &key (shared-args nil)  [Function]

Generate multiple parts of a polyphonic score by calling a function returning musical material multiple times for multiple parts. Returns a headerless score. preview-score describes this format.

Arguments:

  • fn: A function returning an OMN sequence or a sequence of lengths.

  • part-args (plist): Alternating instrument keywords followed by arguments list for `fn' for that instrument/part.

  • shared-args (list): For all instruments/parts, these arguments are appended at end end of its part-specific arguments. They are useful, e.g., for keyword arguments.

Examples:

A random rhythm generated by calling gen-white-noise and vector-to-length with different arguments for different parts.

    (generate-parts 
       #'(lambda (n length low high)  
           (vector-to-length length low high (gen-white-noise n))) 
       '(:vln (10 1/12 1 4) 
         :vlc (12 1/16 1 4))) 

A random rhythm using seed and shared arguments.

    (generate-parts 
       #'(lambda (seed n length low high)  
           (vector-to-length length low high (gen-white-noise n :seed seed))) 
       '(:vln (1) 
         :vlc (2)) 
       :shared-args '(10 1/12 1 4)) 

Notes:

A polyphonic score of only pitches or other parameters without lengths can be generated, but not previewed.

    (preview-score 
      (generate-parts 
       #'(lambda (n range)  
           (vector-to-pitch range (gen-white-noise n))) 
       '(:vln (10 (a3 a4)) 
         :vlc (12 (g2 c4))))) 
     > Error: No length specified before first pitch  
map-parts   score fn part-args &key (parameter nil) (input-parameter nil) (output-parameter nil) (shared-args nil) (flatten nil) (swallow nil)  [Function]

Create or transform a polyphonic score. The original purpose is for creating/transforming musical textures, i.e., relations between polyphonic parts.

Applies function `fn' to parts in `score': this function is a variant of the standard Lisp function `mapcar', but specialised for scores. A score is represented in the format discussed in the documentation of the function `preview-score'. Additional arguments for `fn' can be specified in `part-args', and these argument lists can be different for each part. However, one argument is the part of the score. This argument is marked by an underscore (_) in the argument lists. In the following example, the function `pitch-transpose' is applied to a score with two parts. This function has two required arguments, a transposition interval (measured in semitones), and the pitch sequence or OMN to transpose. The transposition interval for the first part is 4 (major third upwards), and the underscore marks the position of the violin part to transpose, etc.

    (map-parts '(:vln ((h e4))  
     	         :vlc ((h c3)))  
     	   #'pitch-transpose   
     	   '(:vln (4 _)   
     	     :vlc (12 _))) 

Arguments:

  • score (headerless score): See preview-score for format description.

  • fn: A function that expects and returns an OMN sequence or a sequence of parameter values (e.g., lengths, or pitches) as specified in the argument `parameter'.

  • part-args (plist): Alternating instrument keywords (same as in `score') followed by arguments list for `fn' for that instrument/part. If arguments list is :skip for any instrument, then that part is returned unchanged. If `score' contains the same instrument multiple times for expressing polyphony, `part-args' can also specify arguments for these multiple parts with the same name separately.

  • parameter (omn parameter, e.g., :length or :pitch, default nil means processing full OMN expression): If `fn' expects only a single OMN parameter to process, then it can be set here. Otherwise, `fn' expects full OMN sequences.

  • input-parameter (omn parameter): Same as `parameter', but the parameter is only set for `fn' argument -- the parameter returned by `fn' can be set separately. If both `input-parameter' and `parameter' are nil, or `input-parameter' is set to :all, then `fn' expects full OMN sequences.

  • output-parameter (omn parameter): Same as `parameter', but the parameter is only set for `fn' results that are then inserted into the resulting score -- the parameter expected by `fn' can be set separately. If both `output-parameter' and `parameter' are nil, or `output-parameter' is set to :all, then `fn' returns full OMN sequences.

  • shared-args (list): For all instruments/parts, these arguments are appended at end end of its part-specific arguments. They are useful, e.g., for keyword arguments.

  • flatten (Boolean): If T, the parameter sequence -- encoded by `_' in the argument lists, is flattened before the `fn' is applied.

  • swallow (Boolean): If T (and `parameter' or `input-parameter' is set to any parameter except :length), then those parameter values that fall on rests are 'swallow', i.e., skipped. For example, if `parameter' is set to :pitch, and there are rests in the score, then generated/transforemd pitches that would fall on rests are left out.

Examples:

Metric shifting of parts, for details see the documentation of metric-shift

    (map-parts '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) 
                  :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) 
                 #'metric-shift 
                 '(:vln (-q _) 
                   :vlc (-h _) 
                  )) 

An OMN expression to use by several further examples below.

    (setf material '((-3h fs4 pp eb4 <) (q e4 < fs4 <) (3h gs4 mp> a4 > bb4 >) (q a4 pp -) (-5h - g4 pp leg eb4 < leg d4 < leg) (q bb4 < e4 <) (5h g4 mp> leg b4 > leg a4 > leg bb4 > leg d4 > leg) (q gs4 pp -))) 

A strict canon formed with the given material (without any counterpoint rules :) For different parts the material is metrically shifted and transposed.

Note also that map-parts calls can be nested.

    (map-parts  
       (map-parts `(:vl1 ,material 
                    :vl2 ,material   
                    :vla ,material 
                    :vlc ,material) 
                  #'metric-shift  
                  '(:vl1 :skip ;; leave part unchanged 
                    :vl2 (-q _)   
                    :vla (-h _) 
                    :vlc (-h. _))) 
       #'pitch-transpose 
       '(:vl1 (6 _)  
         :vl2 (4 _)   
         :vla (2 _) 
         :vlc :skip)   
       ) 

Simple homorhythmic texture created by randomised transpositions. Each part shares a similar overall pitch profile.

Note that calls can be more concise with a (lambda) function that nests calls to transformation functions -- instead of nesting map-parts as shown above.

    (map-parts `(:vl1 ,material 
                  :vl2 ,material   
     	     :vla ,material 
     	     :vlc ,material) 
     	   #'(lambda (transpose seq) 
     	       ;; static transposition for moving parts into different registers 
     	       (pitch-transpose  
     		transpose  
     		;; randomised transposition of notes in parts 
     		(pitch-transpose-n (rnd 10 :low -2 :high 2) seq))) 
     	   '(:vl1 (7 _)  
     	     :vl2 (0 _)   
     	     :vla (-10 _) 
     	     :vlc (-20 _))) 

Homophonic texture created by random pitch variants (retrograde, inversion etc.). The global pitch profiles of parts differ here, in contrast to the previous example.

    (map-parts  
       `(:vl1 ,material 
         :vl2 ,material   
         :vla ,material 
         :vlc ,material) 
       #'pitch-variant  
       `(:vl1 (_ :transpose 7 :seed 10)  
         :vl2 (_ :transpose 0 :seed 20)   
         :vla (_ :transpose -10 :seed 30) 
         :vlc (_ :transpose -20 :seed 40)) 
        :shared-args '(:variant ?)) 

map-parts-equally   score fn args &key parameter skip  [Function]

Variant of map-parts where all args are shared args.

Arguments:

  • score (headerless score): See preview-score for format description.

  • fn: A function that expects and returns an OMN sequence or a sequence of parameter values (e.g., lengths, or pitches) as specified in the argument `parameter'.

  • args: Arguments list for `fn'. One argument is the part of the score. This argument is marked by an underscore (_) in the argument lists.

  • parameter (omn parameter, e.g., :length or :pitch, default nil means processing full OMN expression): If `fn' expects only single parameter to process, then it can be set here.

  • skip (list of keywords): instruments to skip unprocessed.

Examples:

    (map-parts-equally 
      '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) 
        :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) 
      #'pitch-transpose 
      '(2 _) 
      :parameter :pitch) 
apply-part   instrument score fn args &key (parameter nil)  [Function]

Function applied to a single part of `score'.

Arguments:

  • instrument (symbol): The label of a part in `score'.

  • score (headerless score): See preview-score for format description.

  • fn: A function that expects and returns an OMN sequence or a sequence of parameter values (e.g., lengths, or pitches) as specified in the argument `parameter'.

  • args: Arguments list for `fn'. One argument is the part of the score. This argument is marked by an underscore (_) in the argument lists.

  • parameter (omn parameter, e.g., :length or :pitch, default nil means processing full OMN expression): If `fn' expects only single parameter to process, then it can be set here. Example:

    (apply-part 
      :vlc 
      '(:vln ((q g4) (q. c5 e d5 q e5 f5) (h. e5)) 
        :vlc ((q g3) (q c4 b3 a3 g3) (h. c3))) 
      #'pitch-transpose 
      '(2 _) 
      :parameter :pitch) 
_append-two-parts   score1 score2  [Function]
append-scores   &rest scores  [Function]

Concatenate multiple scores so that they form a sequence in the resulting score. The OMN expression of instruments that are shared between input scores are appended, while instruments that are missing in some input score are padded with rests for the duration of that score.

Note that the function assumes all parts in each score to contain the same overall duration and metric structure.

Arguments:

  • scores: see preview-score for format description of headerless scores.

Examples:

    (setf material '((-3h fs4 pp eb4 <) (q e4 < fs4 <) (3h gs4 mp> a4 > bb4 >) (q a4 pp -))) 
          
     (append-scores `(:vl1 ,material 
                      :vl2 ,(gen-retrograde material :flatten T)) 
                    `(:vl1 ,material 
                      :vlc ,(gen-retrograde material :flatten T)) 
                    `(:vl2 ,material 
                      :vlc ,(gen-retrograde material :flatten T))) 

BUG: If one part misses hierarchic nesting in contrast to others, then this lating nesting is preserved, which can lead to inconsistent nesting (some sections of a part being nested, others are not).

BUG: Does not yet work with scores that express polyphony with multiple instances of the same instrument.

mix-scores   &rest scores  [Function]

Mix multiple scores together to run in parallel. Useful, e.g., for creating melody and polyphonic accompaniment or different textures separately, and then mixing them together.

Arguments:

  • scores: see preview-score for format description of headerless scores.

Examples:

    (let ((material '((-3h fs4 pp eb4 <) (q e4 < fs4 <) (3h gs4 mp> a4 > bb4 >) (q a4 pp -)))) 
        (mix-scores `(:vln ,material) 
                    `(:vlc ,(metric-shift '-h material)))) 
merge-equal-instrument-parts   score  [Function]

If `score' contains multiple instances of the same instrument, then those multiple voices are merged into a polyphonic line (with the time signature taken from the first voice).

Examples:

    (merge-equal-instrument-parts  
       '(:rh ((q c4 d4 e4 f4)) 
         :rh ((q c5 b4 g4 d4)) 
         :lh ((h c3 g3)))) 
     => (:RH ((Q C4C5 D4B4 E4G4 D4F4)) :LH ((H C3 G3))) 
merge-voices2   seq insert bar/beat  [Function]

Merges multiple monophonic lines resulting in a polyphonic part.

Arguments:

  • seq (OMN sequence, must be nested): Voice to which other voices are added. The result retains the time signatures of SEQ.

  • insert (list of flat OMN sequences): Voices to merge into SEQ. Their time signatures are overwritten by the meter of SEQ.

  • bar/beat (list): List of start times of inserted sequences.

Each INSERT start time is specified in the following format, where <bar-number> is a 1-based bar number (an int), <beat-number> is a 1-based beat number (an int), and <beat-subdivision> is the divisor for the beat number (also an int).

    (<bar-number> (<beat-number> <beat-subdivision>)) 

For example, (3 (2 4)) indicates the 2nd quarter note in the 3rd bar.

Examples:

Merge two OMN sequences.

    (merge-voices2 '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) 
                     '((q a4 a4 a4)) 
                     '((2 (2 8))))   

Merge three sequences.

    (merge-voices2 '((q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4) (q c4 c4 c4 c4)) 
                    '((q b5 b5 b5) 
                      (e a4 a4 a4)) 
                    '((2 (2 8)) 
                      (3 (2 16)))) 

See Also:

The built-in function `merge-voices' is similar, but does not support shifting/offsetting added voices in time.

get-instruments   score  [Function]

Returns all instruments of `score', a headerless score (see preview-score for its format).

get-part-omn   instrument score  [Function]

Returns the part (OMN expression) of `instrument' in `score', a headerless score (see preview-score for its format).

BUG: does not yet allow access to higher position of equally named parts.

get-parts-omn   score  [Function]

Returns a list of all OMN parts of `score', a headerless score (see preview-score for its format).

replace-instruments   new old score  [Function]

Replaces old instruments by new instruments in a score.

Arguments:

  • new (list of keywords): New instruments to use.

  • old (list of keywords): List of instruments in `score' to be replaced. Must have same length as `new'.

  • score (a headerless score): See preview-score for its format.

Examples:

    (replace-instruments '(:trp :trb) '(:vl2 :vlc) 
     '(:vl1 (h g4) 
       :vl2 (h e4) 
       :vla (h c4) 
       :vlc (h c3))) 
replace-part-omn   instrument new-part score  [Function]

Replaces the part (OMN expression) of `instrument' in `score' with `new-part'.

Examples:

    (replace-part-omn  :vlc 
      '((h g3)) 
      '(:vln ((h e4)) 
        :vlc ((h c3)))) 
split-part   instrument orig-score score-to-insert  [Function]

Replaces part of `instrument' in `orig-score' with `score-to-insert'.

Examples:

    (split-part :vl2 
     '(:vl1 (h g4) 
       :vl2 (h e4) 
       :vla (h c4) 
       :vlc (h c3)) 
      '(:vl2_div1 (h f4) 
        :vl2_div2 (h e4))) 

Split divisi strings into parts

    (setf my-score 
         '(:vl1 (h g4b4 g4a4) 
           :vl2 (h e4 d4) 
           :vla (h c4 b3) 
           :vlc (h c3 g3))) 

    (setf divisi-part (single-events (pitch-melodize (get-part-omn :vl1 my-score)))) 

    (preview-score 
      (split-part :vl1 
                  my-score 
                  `(:vl1_div1 ,(flatten (tu:at-even-position divisi-part)) 
                    :vl1_div2 ,(flatten (tu:at-odd-position divisi-part))))) 
remove-part   instrument score  [Function]

Removes `instrument' and its OMN expression from `score'.

Examples:

    (remove-part :vl2 
     '(:vl1 (h g4) 
       :vl2 (h e4) 
       :vla (h c4) 
       :vlc (h c3))) 
remove-parts   instruments score  [Function]

Removes all `instruments' and their OMN expressions from `score'.

Examples:

    (remove-parts '(:vl1 :vl2) 
     '(:vl1 (h g4) 
       :vl2 (h e4) 
       :vla (h c4) 
       :vlc (h c3))) 
extract-parts   instruments score  [Function]

Extracts all `instruments' and their OMN expressions from `score'.

Examples:

    (extract-parts '(:vl1 :vla) 
     '(:vl1 (h g4) 
       :vl2 (h e4) 
       :vla (h c4) 
       :vlc (h c3))) 
reorder-parts   instruments-in-order score  [Function]

Changes the order of instruments in `score' to the order given in `instruments-in-order'. Only the instruments included in `instruments-in-order' are parts of the resulting score.

unify-time-signature   instrument-with-time-signature score  [Function]

Rebar music of all parts in `score' to match the meter of `instrument-with-time-signature'.

split-score-at-shared-rests   score  [Function]

Splits headerless `score' into list of headerless scores. `score' is split at the end of every bar, where each part has either a rest at the end of this bar or at the beginning of the next bar.

The bar positions (zero-based bar numbers) at which the score was split is returned as second value.

This function is useful to split longer input scores, for which the function `revise-score-harmonically' could take a long time.

All parts in score must share the same time signatures (nesting). You may want to first use `unify-time-signature' if necessary.

Examples:

    (split-score-at-shared-rests 
      '(:vln ((q g4) (q. c5 e d5 q e5 -q) (h e5 -q)) 
        :vlc ((q g3) (q c4 b3 h a3) (-q c3 d3)))) 
     => ((:vln ((q g4) (q. c5 e d5 q e5 -q)) 
          :vlc ((q g3) (q c4 b3 h a3))) 
         (:vln ((h e5 -q)) 
          :vlc ((-q c3 d3)))) 
        (0 2) 
split-score-at-bar-boundaries   score &optional positions  [Function]

Splits headerless `score' into list of headerless scores. `score' is split at the end of bars given at `positions'.

This function is useful to split longer input scores, for which the function `revise-score-harmonically' could take a long time.

Arguments:

  • score: a headerless score

  • positions (single integer; list of integers; or NIL): zero-based representation indicating after which bars score should be split. If positions is...

    • A list of integers, the score is split after each indicated bar number.

    • A single integer `n', the score is split after every `n' bars. For example, if `n' is 2, the score is split after every 2nd bar.

    • `nil' (default), the score is split after every bar up to the end of the score

All parts in score must share the same time signatures (nesting). You may want to first use `unify-time-signature' if necessary.

The bar positions (zero-based bar numbers) at which the score was split is returned as second value.

score-duration   score  [Function]

Returns total duration of `score'.

unify-part-durations   score  [Function]

Ensure all parts of `score' are of the same duration by effectively looping shorter parts until they are as long as the longest part. The resulting time signatures of all parts follows that of the the first longest part. You may use the function `unify-time-signature' before if you want to enforce time signatures of a different part instead.

An accordingly revised score is returned as first, and the full duration of `score' as a second value.