./../../src/rhythm.lsp

## linked-named-object/rhythm [ Classes ]

[ Top ] [ linked-named-object ] [ Classes ]

NAME

     rhythm

     File:             rhythm.lsp

     Class Hierarchy:  named-object -> linked-named-object -> rhythm

     Version:          1.0.0

     Project:          slippery chicken (algorithmic composition)

     Purpose:          Implementation of the rhythm class for parsing and
                       storing the properties of rhythms.

     Author:           Michael Edwards: m@michael-edwards.org

     Creation date:    11th February 2001

     $$ Last modified: 15:09:20 Wed Nov 28 2012 GMT

     SVN ID: $Id: rhythm.lsp 3155 2012-12-06 16:19:43Z medward2 $

## rhythm/accented-p [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

     05 Apr 2011

DESCRIPTION

     Check the MARKS slot of a given rhythm object to determine if it possesses
     an accent mark. The rhythm object may also possess other marks as well.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     If the accent mark ('a) is indeed found in the MARKS slot of the given
     rhythm object, the tail of the list of marks contained in that slot is
     returned; otherwise NIL is returned.

EXAMPLE

    ;; Make a rhythm object, add an accent, and test for the presence of the accent
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (accented-p r))

    => (A)

    ;; Check if an accent mark is among all marks in the MARKS slot
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 's)
      (add-mark-once r 'a)
      (accented-p r))

    => (A S)

    ;; Add an accent and staccato, then remove the accent and test for it
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (add-mark-once r 's)
      (rm-marks r 'a)
      (accented-p r))

    => NIL

SYNOPSIS

    (defmethod accented-p ((r rhythm))

## rhythm/add [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Create a new rhythm object with a duration that is equal to the sum of the
     duration of two other given rhythm objects.

     NB: This method only returns a single rhythm rather than a list with
         ties. Thus q+s, for example, returns TQ...

     If the resulting duration cannot be presented as a single, notatable
     rhythm, the DATA slot of the resulting rhythm object is set to NIL, though
     the VALUE and DURATION slots are still set with the corresponding numeric
     values.

ARGUMENTS

     - A first rhythm object.
     - A second rhythm object.

OPTIONAL ARGUMENTS

     - T or NIL to indicate whether a warning is printed when a rhythm cannot be
       made because the resulting value is 0 or a negative duration. Default =
       NIL (no warning issued).

RETURN VALUE

     A rhythm object. Returns NIL when the object cannot be made.

EXAMPLE

    ;; A quarter plus an eighth makes a dotted quarter
    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'e)))
      (add r1 r2))

    =>
    RHYTHM: value: 2.6666666666666665, duration: 1.5, rq: 3/2, is-rest: NIL, score-rthm: 4.0f0.,
            undotted-value: 4, num-flags: 0, num-dots: 1, is-tied-to: NIL,
            is-tied-from: NIL, compound-duration: 1.5, is-grace-note: NIL,
            needs-new-note: T, beam: NIL, bracket: NIL, rqq-note: NIL,
            rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: 4,
            tuplet-scaler: 1, grace-note-duration: 0.05
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: Q., tag: NIL,
    data: Q.

    ;; A quarter plus a triplet-eighth is presented as a triplet-half
    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'te)))
      (data (add r1 r2)))

    => TH

    ;; A quarter plus a septuplet-16th cannot be represented as a single, notatable
    ;; rhythm and therefore produces an object with a VALUE and DURATION but no
    ;; DATA
    (let ((r1 (make-rhythm 4))
          (r2 (make-rhythm 28)))
      (print (value (add r1 r2)))
      (print (duration (add r1 r2)))
      (print (data (add r1 r2))))

    =>
    3.5
    1.1428571428571428
    NIL

SYNOPSIS

    (defmethod add ((r1 rhythm) (r2 rhythm) &optional warn)

## rhythm/add-mark [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Add an articulation, dynamic, slur or any other mark to a rhythm (also
     useful in the event subclass for changing note heads etc.) Multiple marks
     can be added separately and consecutively to the same rhythm object.

     A warning is printed if the same mark is added to the same rhythm object
     more than once.

     NB: This method checks to see if the mark added is a valid mark and will
         warn if it doesn't exist (but it will still add it, in case you have
         your own processing logic for it).

ARGUMENTS

     - A rhythm object.
     - A mark.

OPTIONAL ARGUMENTS

     - T or NIL to indicated whether to issue a warning when trying to add marks
       to a rest. Default = NIL.

RETURN VALUE

     Always T.

EXAMPLE

    (let ((r (make-rhythm 'q)))
      (marks r))

    => NIL

    (let ((r (make-rhythm 'q)))
      (add-mark r 'a))

    => T

    (let ((r (make-rhythm 'q)))
      (add-mark r 's)
      (marks r))

    => (S)

    (let ((r (make-rhythm 'q)))
      (add-mark r 'col-legno)
      (add-mark r 'as)
      (add-mark r 'x-head)
      (marks r))

    => (X-HEAD AS COL-LEGNO)

    (let ((r (make-rhythm 'q)))
      (add-mark r 's)
      (add-mark r 's))

    => T
    WARNING: rhythm::add-mark: S already present but adding again!:

    (let ((r (make-rhythm 'e :is-rest t)))
      (add-mark r 'at)
      (print (is-rest r))
      (print (marks r)))

    =>
    T
    (AT)

    (let ((r (make-rhythm 'e :is-rest t)))
      (add-mark r 'at t))

    => T
    WARNING:
    [...]
    rhythm::add-mark: add AT to rest?

SYNOPSIS

    (defmethod add-mark ((r rhythm) mark &optional warn-rest)

## rhythm/add-mark-once [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

     26 Jul 2011 (Pula)

DESCRIPTION

     Apply the given mark to the given rhythm object, but do so only if the
     given rhythm object does not yet have the mark.

ARGUMENTS

     - A rhythm object.
     - A mark.

OPTIONAL ARGUMENTS

     - T or NIL to indicate whether or not to print a warning when attempting to
       apply a mark to a rest.

RETURN VALUE

     Returns T if the mark is successfully applied (if the rhythm object did not
     already possess the mark), otherwise NIL if the mark was not applied
     because the rhythm object already had it.

EXAMPLE

    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a))

    => T

    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (marks r))

    => (A)

    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (add-mark-once r 'a))

    => NIL

    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (add-mark-once r 'a)
      (marks r))

    => (A)

SYNOPSIS

    (defmethod add-mark-once ((r rhythm) mark &optional warn-rest)

## rhythm/begin-slur-p [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Check to see if the MARKS slot of a given rhythm object contains a mark for
     the beginning of a slur ('beg-sl). The rhythm object may also possess other
     marks as well.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     If the 'beg-sl mark is indeed found in the MARKS slot of the given rhythm
     object, the tail of the list of marks contained in that slot is returned;
     otherwise NIL is returned.

EXAMPLE

    ;; Create a rhythm object, add a 'beg-sl mark and check for it
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'beg-sl)
      (begin-slur-p r))

    => (BEG-SL)

    ;; Add several marks to a rhythm object and check for 'beg-sl
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s beg-sl) do (add-mark-once r m))
      (begin-slur-p r))

    => (BEG-SL S A)

    ;; Add a 'beg-sl mark to a rhythm object, then delete it and check for it
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'beg-sl)
      (rm-marks r 'beg-sl)
      (begin-slur-p r))

    => NIL

SYNOPSIS

    (defmethod begin-slur-p ((r rhythm))

## rhythm/delete-beam [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Removes indication for the start (1) or end (0) of a beam from the BEAM
     slot of a given rhythm object, replacing them with NIL.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     Always returns NIL.

EXAMPLE

    ;; Manually set the beam of a rhythm object and delete it to see result NIL
    (let ((r (make-rhythm 'e)))
      (setf (beam r) 1)
      (delete-beam r))

    => NIL

    ;; Make a rthm-seq-bar object with beam indications, then check the BEAM slot
    ;; of each rhythm object in the rthm-seq-bar object.
    (let ((rsb (make-rthm-seq-bar '((2 4) - s s e - q))))
      (loop for r in (rhythms rsb) collect (beam r)))

    => (1 NIL 0 NIL)

    ;; Make a rthm-seq-bar object with beam indications, delete them all, then
    ;; check the beam slot of each rhythm object in the rthm-seq-bar object.
    (let ((rsb (make-rthm-seq-bar '((2 4) - s s e - q))))
      (loop for r in (rhythms rsb) do (delete-beam r))
      (loop for r in (rhythms rsb) collect (beam r)))

    => (NIL NIL NIL NIL)

SYNOPSIS

    (defmethod delete-beam ((r rhythm))

## rhythm/delete-marks [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Delete any marks in the MARKS slot of an event object created within a
     rhythm object, replacing the entire list of the MARKS slot with NIL.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     Always returns NIL.

EXAMPLE

    ;; The method returns NIL
    (let ((r (make-rhythm (make-event 'c4 'q))))
      (loop for m in '(a s pizz) do (add-mark-once r m))
      (delete-marks r))

    => NIL

    ;; Create a rhythm object consisting of an event object and print the default
    ;; contents of the MARKS slot. Set the MARKS slot to contain three marks and
    ;; print the result. Apply the delete-marks method and print the result.
    (let ((r (make-rhythm (make-event 'c4 'q))))
      (print (marks r))
      (loop for m in '(a s pizz) do (add-mark-once r m))
      (print (marks r))
      (delete-marks r)
      (print (marks r)))

    =>
    NIL
    (PIZZ S A)
    NI

SYNOPSIS

    (defmethod delete-marks ((r rhythm))

## rhythm/duration-secs [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Determine the absolute duration in seconds of a given rhythm object at a
     given quarter-note tempo. If no tempo is specified, a tempo of 60 is
     assumed.

ARGUMENTS

     - A rhythm object.

OPTIONAL ARGUMENTS

     - A numerical tempo value based on quarter-note beats per minute.

RETURN VALUE

     A real number (floating point) representing the absolute duration of the
     given rhythm object in seconds.

EXAMPLE

    ;; Determine the duration in seconds of a quarter note with a default tempo of
    ;;; quarter = 60
    (let ((r (make-rhythm 'q)))
      (duration-secs r))

    => 1.0

    ;; Specifying a different tempo results in a different duration in seconds
    (let ((r (make-rhythm 'q)))
      (duration-secs r 96))

    => 0.625

SYNOPSIS

    (defmethod duration-secs ((r rhythm) &optional (tempo 60))

## rhythm/end-slur-p [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Check to see if the MARKS slot of a given rhythm object contains a mark for
     the ending of a slur ('end-sl). The rhythm object may also possess other
     marks as well.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     If the 'end-sl mark is indeed found in the MARKS slot of the given rhythm
     object, the tail of the list of marks contained in that slot is returned;
     otherwise NIL is returned.

EXAMPLE

    ;; Create a rhythm object, add a 'end-sl mark and check for it
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'end-sl)
      (end-slur-p r))

    => (END-SL)

    ;; Add several marks to a rhythm object and check for 'end-sl
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s end-sl) do (add-mark-once r m))
      (end-slur-p r))

    => (END-SL S A)

    ;; Add an 'end-sl mark to a rhythm object, then delete it and check for it
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'end-sl)
      (rm-marks r 'end-sl)
      (end-slur-p r))

    => NIL

SYNOPSIS

    (defmethod end-slur-p ((r rhythm))

## rhythm/force-rest [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Force the given rhythm object to be a rest.

ARGUMENTS

     - A rhythm object.

RETURN VALUE

     A rhythm object.

EXAMPLE

    (let ((r (make-rhythm 8)))
      (force-rest r)
      (is-rest r))

    => T

SYNOPSIS

    (defmethod force-rest ((r rhythm))

## rhythm/has-mark [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Check to see if a given rhythm object possesses a specified mark.

ARGUMENTS

     - A rhythm object.
     - A mark.

RETURN VALUE

     If the specified mark is indeed found in the MARKS slot of the given rhythm
     object, the tail of the list of marks contained in that slot is returned;
     otherwise NIL is returned.

EXAMPLE

    ;; Add a specific mark and check to see if the rhythm object has it.
    (let ((r (make-rhythm 'q)))
      (add-mark r 'a)
      (has-mark r 'a))

    => (A)

    ;; Check to see if the given rhythm object possess a mark we know it doesn't.
    (let ((r (make-rhythm 'q)))
      (add-mark r 'a)
      (has-mark r 's))

    => NIL

SYNOPSIS

    (defmethod has-mark ((r rhythm) mark &optional (test #'equal))

## rhythm/is-multiple [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Determines if the value of one rhythm object is a multiple of the value of
     a second rhythm object. This is established by dividing the one by the
     other and checking to see if the quotient is a whole number.

ARGUMENTS

     - A first rhythm object.
     - A second rhythm object.

RETURN VALUE

     Returns T if true and NIL if not. Always also returns the quotient.

EXAMPLE

    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'e)))
      (is-multiple r1 r2))

    => T, 2.0

    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'e.)))
      (is-multiple r1 r2))

    => NIL, 1.3333333333333333

SYNOPSIS

    (defmethod is-multiple ((r1 rhythm) (r2 rhythm))

## rhythm/make-rhythm [ Functions ]

[ Top ] [ rhythm ] [ Functions ]

DESCRIPTION

     Make a rhythm object.

ARGUMENTS

     - A duration either as a numeric representation of a rhythm (subdivision of
       a whole note; 2 = half note, 4 = quarter, 8 = eighth etc), a quoted
       alphabetic shorthand for a duration (ie, 'h, 'q, 'e etc.), or an absolute
       duration in seconds.

OPTIONAL ARGUMENTS

     keyword arguments:
     - :is-rest. T or NIL to denote whether the given duration is a rest or
       not. T = rest. Default = NIL.
     - :is-tied-to. T or NIL to denote whether the given duration is tied later
       to the next duration in a given rthm-seq-bar/rthm-seq object. T =
       tied. Default = NIL.
     - :duration. Indicates whether the duration argument has been given as a
       duration in seconds, not a known rhythm like 'e or 8. T indicates that
       the duration is a duration in seconds. Default = NIL.
     - :tempo. Indicates the tempo for the given rhythm. This is not related to
       any tempi applied, rather one that is reflected in the duration-in-tempo
       slot of event.

RETURN VALUE

     A rhythm object.

EXAMPLE

    (make-rhythm 16)

    =>
    RHYTHM: value: 16.0, duration: 0.25, rq: 1/4, is-rest: NIL, score-rthm: 16.0,
            undotted-value: 16, num-flags: 2, num-dots: 0, is-tied-to: NIL,
            is-tied-from: NIL, compound-duration: 0.25, is-grace-note: NIL,
            needs-new-note: T, beam: NIL, bracket: NIL, rqq-note: NIL,
            rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: 16,
            tuplet-scaler: 1, grace-note-duration: 0.05
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: 16, tag: NIL,
    data: 16

    (make-rhythm 16 :is-rest t :is-tied-to t)

    =>
    RHYTHM: value: 16.0, duration: 0.25, rq: 1/4, is-rest: T, score-rthm: 16.0,
            undotted-value: 16, num-flags: 2, num-dots: 0, is-tied-to: T,
            is-tied-from: NIL, compound-duration: 0.25, is-grace-note: NIL,
            needs-new-note: NIL, beam: NIL, bracket: NIL, rqq-note: NIL,
            rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: 16,
            tuplet-scaler: 1, grace-note-duration: 0.05
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: 16, tag: NIL,
    data: 16

    (make-rhythm .23 :duration t)

    =>
    RHYTHM: value: 17.391304, duration: 0.23, rq: 23/100, is-rest: NIL, score-rthm: NIL,
            undotted-value: -1.0, num-flags: 0, num-dots: 0, is-tied-to: NIL,
            is-tied-from: NIL, compound-duration: 0.23, is-grace-note: NIL,
            needs-new-note: T, beam: NIL, bracket: NIL, rqq-note: NIL,
            rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: -1,
            tuplet-scaler: 1, grace-note-duration: 0.05
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: NIL, tag: NIL,
    data: NIL

SYNOPSIS

    (defun make-rhythm (rthm &key (is-rest nil) (is-tied-to nil) (duration nil)
                        (tempo 60.0))

## rhythm/replace-mark [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Replace a specified mark of a given rhythm object with a second specified
     mark. If a rhythm object contains more than one mark, individual marks can
     be changed without modifying the remaining marks.

ARGUMENTS

     - A rhythm object.
     - The mark to be replaced.
     - The new mark.

RETURN VALUE

     Returns the new value of the MARKS slot of the given object.

EXAMPLE

    ;; Make a rhythm object, add the mark 'a, then replace 'a with 's
    (let ((r (make-rhythm 'q)))
      (add-mark r 'a)
      (replace-mark r 'a 's))

    => (S)

    ;; Make a rhythm object, add a list of marks, replace just the 'pizz mark with
    ;; a 'batt mark

    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s pizz col-legno) do (add-mark-once r m))
      (replace-mark r 'pizz 'batt))

    => (COL-LEGNO BATT S A)

SYNOPSIS

    (defmethod replace-mark ((r rhythm) what with &optional ignore)

## rhythm/rhythm-equal [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Compares the values of two rhythm objects to determine if they are equal.

     NB rhythm-equal compares the values only, so rhythms with the same values
        will still be considered equal even if their other attributes (such as
        :is-rest and :is-tied-to etc.) are different.

ARGUMENTS

     - A first rhythm object.
     - A second rhythm object.

RETURN VALUE

     T if the values of the given rhythm objects are equal, else NIL.

EXAMPLE

    (let ((r1 (make-rhythm 4))
          (r2 (make-rhythm 4)))
      (rhythm-equal r1 r2))

    => T

    (let ((r1 (make-rhythm 4))
          (r2 (make-rhythm 8)))
      (rhythm-equal r1 r2))

    => NIL

    (let ((r1 (make-rhythm 4 :is-rest T))
          (r2 (make-rhythm 4 :is-rest NIL)))
      (rhythm-equal r1 r2))

    => T

    (let ((r1 (make-rhythm 4 :is-tied-to T))
          (r2 (make-rhythm 4 :is-tied-to NIL)))
      (rhythm-equal r1 r2))

    => T

SYNOPSIS

    (defmethod rhythm-equal ((r1 rhythm) (r2 rhythm))

## rhythm/rhythm-list [ Functions ]

[ Top ] [ rhythm ] [ Functions ]

DESCRIPTION

     Create a list of rhythms from symbols, possibly involving ties and not
     needing meters etc. (i.e. not as strict as rthm-seq).

ARGUMENTS

     - The list of rhythm symbols.

OPTIONAL ARGUMENTS

     - T or NIL indicates whether to create a circular-sclist from the
       result. If NIL, a simple list will be returned (default = NIL).

RETURN VALUE

     A list or circular-sclist of the rhythm objects.

EXAMPLE

    ;; Create a list of rhythm objects
    (rhythm-list '(q w+e q. h.+s e.+ts))

    =>(
    RHYTHM: value: 4.0f0, duration: 1.0
    [...]
    RHYTHM: value: 1.0f0, duration: 4.0
    [...]
    RHYTHM: value: 8.0f0, duration: 0.5
    [...]
    RHYTHM: value: 2.6666666666666665, duration: 1.5
    [...]
    RHYTHM: value: 1.3333333333333333, duration: 3.0
    [...]
    RHYTHM: value: 16.0f0, duration: 0.25
    [...]
    RHYTHM: value: 5.333333333333333, duration: 0.75
    [...]
    RHYTHM: value: 24.0f0, duration: 0.16666666666666666
    )

    ;; Collect the data from each of the individual rhythm objects in the list.
    (let ((rl (rhythm-list '(q w+e q. h.+s e.+ts))))
      (print (loop for r in rl collect (data r))))

    => (Q "W" "E" Q. "H." "S" "E." "TS")

    ;; Set the optional argument to T to create a circular-sclist instead
    (rhythm-list '(q w+e q. h.+s e.+ts) t)

    =>
    CIRCULAR-SCLIST: current 0
    SCLIST: sclist-length: 8, bounds-alert: T, copy: T
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: NIL, tag: NIL,
    data: (
    [...]
    )

    ;; Create a circular-sclist and check that it's a circular-sclist using cscl-p
    (let ((rl (rhythm-list '(q w+e q. h.+s e.+ts) t)))
      (cscl-p rl))

    => T

SYNOPSIS

    (defun rhythm-list (rthms &optional circular)

## rhythm/rhythm/ [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Determines the ratio of one rhythm object's duration to that of a second
     rhythm object by use of division.

ARGUMENTS

     - A rhythm object.
     - A second rhythm object.

RETURN VALUE

     A number.

EXAMPLE

    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'e)))
      (rhythm/ r1 r2))

    => 2.0

    (let ((r1 (make-rhythm 'q))
          (r3 (make-rhythm 's.)))
      (rhythm/ r1 r3))

    => 2.6666667

SYNOPSIS

    (defmethod rhythm/ ((r1 rhythm) (r2 rhythm))

## rhythm/rm-marks [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Remove a specified mark (or a list of specified marks) from the MARKS slot
     of a given rhythm object. If the mark specified is not present in the given
     rhythm object's MARKS slot, a warning is printed. If some marks of a list
     of specified marks are present in the rhythm object's MARKS slot and other
     aren't, those that are will be removed and a warning will be printed for
     the rest.

ARGUMENTS

     - A rhythm object.
     - A mark or list of marks.

OPTIONAL ARGUMENTS

     - T or NIL to indicate whether a warning is to be printed if the specified
       mark is not present in the given rhythm object's MARKS slot.

RETURN VALUE

     Always returns NIL.

EXAMPLE

    ;; The method itself returns NIL
    (let ((r (make-rhythm 'q)))
      (add-mark-once r 'a)
      (rm-marks r 'a))

    => NIL

    ;; Adding a list of marks to r, then removing only 's
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s pizz col-legno x-head) do
           (add-mark-once r m))
      (rm-marks r 's)
      (marks r))

    => (X-HEAD COL-LEGNO PIZZ A)

    ;; Removing a list of marks from r
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s pizz col-legno x-head) do
           (add-mark-once r m))
      (rm-marks r '(s a))
      (marks r))

    => (X-HEAD COL-LEGNO PIZZ)

    ;; Attempting to remove a mark that isn't present results in a warning
    ;; being printed by default
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s pizz col-legno x-head) do
           (add-mark-once r m))
      (rm-marks r 'zippy))

    => NIL
    WARNING: rhythm::rm-marks: no mark ZIPPY in (X-HEAD COL-LEGNO PIZZ S A)

    ;; Suppress printing the warning when the specified mark isn't present
    (let ((r (make-rhythm 'q)))
      (loop for m in '(a s pizz col-legno x-head) do
           (add-mark-once r m))
      (rm-marks r 'zippy nil))

    => NIL

SYNOPSIS

    (defmethod rm-marks ((r rhythm) marks &optional (warn t))

## rhythm/scale [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Change the value of a rhythm object's duration value by a specified
     scaling factor.

ARGUMENTS

     - A rhythm object.
     - A scaling factor.

OPTIONAL ARGUMENTS

     - <clone>. This argument determines whether a new rhythm object is made or
       the duration value of the old object is replaced. When set to T, a new
       object is made based on the duration value of the original. When set to
       NIL, the original duration value is replaced (see example). Default = T.

RETURN VALUE

     A rhythm object.

EXAMPLE

    (let ((r (make-rhythm 4)))
      (data (scale r 2)))

    => H

    (let ((r (make-rhythm 4)))
      (data (scale r 3)))

    => H.

    (let ((r (make-rhythm 4)))
      (data (scale r .5)))

    => E

    (let ((r (make-rhythm 4)))
      (dotimes (i 5)
        (print (value (scale r .5)))))

    =>
    8.0
    8.0
    8.0
    8.0
    8.0

    (let ((r (make-rhythm 4)))
      (dotimes (i 5)
        (print (value (scale r .5 nil)))))

    =>
    8.0
    16.0
    32.0
    64.0
    128.0

SYNOPSIS

    (defmethod scale ((r rhythm) scaler &optional (clone t) ignore1 ignore2)

## rhythm/subtract [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DESCRIPTION

     Create a new rhythm object with a duration that is equal to the difference
     between the duration of two other given rhythm objects.

     NB: This method only returns a single rhythm rather than a list with
         ties. Thus h - e., for example, returns TQ...

     If the resulting duration cannot be presented as a single rhythm, the DATA
     slot of the resulting rhythm object is set to NIL, though the VALUE and
     DURATION slots are still set with the corresponding numeric values.

     If the resulting duration is equal to or less than 0, NIL is returned and
     an optional warning may be printed.

ARGUMENTS

     - A first rhythm object.
     - A second rhythm object.

OPTIONAL ARGUMENTS

     - T or NIL to indicate whether a warning is to be printed when the
       resulting duration is less than or equal to 0. Default = 0.

RETURN VALUE

     A rhythm object if the resulting duration is greater than 0, else NIL and
     the optional warning.

EXAMPLE

    ;; Make a new rhythm object with a duration equal to one quarter minus one
    ;; eighth.
    (let ((r1 (make-rhythm 'q))
          (r2 (make-rhythm 'e)))
      (subtract r1 r2))

    =>
    RHYTHM: value: 8.0f0, duration: 0.5, rq: 1/2, is-rest: NIL, score-rthm: 8.0f0,
            undotted-value: 8, num-flags: 1, num-dots: 0, is-tied-to: NIL,
            is-tied-from: NIL, compound-duration: 0.5, is-grace-note: NIL,
            needs-new-note: T, beam: NIL, bracket: NIL, rqq-note: NIL,
            rqq-info: NIL, marks: NIL, marks-in-part: NIL, letter-value: 8,
            tuplet-scaler: 1, grace-note-duration: 0.05
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: E, tag: NIL,
    data: E

    ;; A half minus a dotted eighth is represented as a triplet half
    (let ((r1 (make-rhythm 'h))
          (r2 (make-rhythm 'e.)))
      (data (subtract r1 r2)))

    => TQ...

    ;; If the resulting duration is 0 or less, return NIL, with no warning by
    ;; default
    (let ((r1 (make-rhythm 'e))
          (r2 (make-rhythm 'q)))
      (subtract r1 r2))

    => NIL

    ;; Setting the optional argument to t returns a warning when the resulting
    ;; duration is less than 0
    (let ((r1 (make-rhythm 'e))
          (r2 (make-rhythm 'q)))
      (subtract r1 r2 t))

    => NIL
    WARNING: rhythm::arithmetic: new duration is -0.5; can't create rhythm

    ;; Subtracting a septuplet-16th from a quarter results in a duration that
    ;; cannot be represented as a single rhythm, therefore setting the DATA to NIL
    ;; while VALUE and DURATION are still set.
    (let ((r1 (make-rhythm 4))
          (r2 (make-rhythm 28)))
      (print (value (subtract r1 r2)))
      (print (duration (subtract r1 r2)))
      (print (data (subtract r1 r2))))

    =>
    4.666666666666666
    0.8571428571428572
    NIL

SYNOPSIS

    (defmethod subtract ((r1 rhythm) (r2 rhythm) &optional warn)