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.1.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:  12:09:13 Wed Jul 17 2024 CEST

 SVN ID: $Id$

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 warn-again)

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/end-tie [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 September 14th 2018, Heidhausen

DESCRIPTION

 return T or NIL depending on whether the rhythm/event is the end of a tie
 (tied-to but not tied-from)  

ARGUMENTS

 the rhythm/event object

RETURN VALUE

 T or NIL

SYNOPSIS

(defmethod end-tie ((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/get-proportions [ Functions ]

[ Top ] [ rhythm ] [ Functions ]

DATE

 15th February 2022, Heidhausen

DESCRIPTION

 Get the normalised proportions of a list of rhythms, i.e. the durational
 relationships of one rhythm to another. By normalised here it is meant that
 the returned list will sum to 1.0. Implicit there is that proportions are
 expressed as floating-point fractions of 1.0, not as rationals.

 NB this works with the rhythm-slot only of rhythm objects, not
 compound-duration

ARGUMENTS

 a list of rhythm objects or symbols/numbers that represent rhythms.

RETURN VALUE

 a list of floats

EXAMPLE

(get-proportions '(e e q e. s q)) --> (0.125 0.125 0.25 0.1875 0.0625 0.25)

SYNOPSIS

(defun get-proportions (rhythms)

rhythm/has-dynamic [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 December 3rd 2023

DESCRIPTION

 Determine whether a rhythm object has any dynamics in its marks slot.

ARGUMENTS

 - a rhythm object

RETURN VALUE

 The dynamic as a symbol (e.g. pp) or NIL if there are none.

SYNOPSIS

(defmethod has-dynamic ((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/in-tie [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 September 14th 2018, Heidhausen

DESCRIPTION

 return T or NIL depending on whether the rhythm/event is part of a tie
 (either tied-from or tied-to)  

ARGUMENTS

 the rhythm/event object

RETURN VALUE

 T or NIL

SYNOPSIS

(defmethod in-tie ((r rhythm))

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/just-attacks [ Functions ]

[ Top ] [ rhythm ] [ Functions ]

DATE

 February 9th 2022

DESCRIPTION

 Remove any rhythms/events from a list that don't represent an attack,
 i.e. remove all rests and those tied-to.

ARGUMENTS

 a list of rhythm/event objects

RETURN VALUE

 the list purged of all rests and those tied-to

SYNOPSIS

(defun just-attacks (rthms)

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 and is used only when
    :duration is set to figure out the rhythm type (1/8, 1/4 etc.) from the
    two values. So 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 is-tied-to is-tied-from duration
                           (tempo 60.0))

rhythm/mid-tie [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 September 14th 2018, Heidhausen
 
 DESCRIPTION return T or NIL depending on whether the rhythm/event is in the
 middle of a tie (i.e. both tied-from or tied-to are T)

ARGUMENTS

 the rhythm/event object

RETURN VALUE

 T or NIL

SYNOPSIS

(defmethod mid-tie ((r rhythm))

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. Bear in mind that after scaling, depending on the
 complexity of the rhythm, the data slot may no longer accurately represent
 the new rhythmic value (though of course the value, duration, and rq, etc.,
 slots will). 

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

SYNOPSIS

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

rhythm/scale-as-rests [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 September 29th 2020, Heidhausen

DESCRIPTION

 Sometimes you don't want to actually scale a rhythm/event's duration rather
 stretch it out with rests. This method will leave the rhythm object intact
 (or cloned) before then cloning it a given number of times but as a rest.

ARGUMENTS

 - the rhythm object
 - the scaler (integer)

OPTIONAL ARGUMENTS

 - T or NIL: whether to clone the first argument

RETURN VALUE

 a list of rhythm objects

SYNOPSIS

(defmethod scale-as-rests ((r rhythm) scaler &optional (clone t))

rhythm/start-tie [ Methods ]

[ Top ] [ rhythm ] [ Methods ]

DATE

 September 14th 2018, Heidhausen

DESCRIPTION

 return T or NIL depending on whether the rhythm/event is the start of a tie
 (tied-from but not tied-to)  

ARGUMENTS

 the rhythm/event object

RETURN VALUE

 T or NIL

SYNOPSIS

(defmethod start-tie ((r rhythm))

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)