palette/set-palette [ Classes ]

[ Top ] [ palette ] [ Classes ]

NAME

 set-palette
 
 File:             set-palette.lsp

 Class Hierarchy:  named-object -> linked-named-object -> sclist -> 
                   circular-sclist -> assoc-list -> recursive-assoc-list ->
                   palette -> set-palette

 Version:          1.1.0

 Project:          slippery chicken (algorithmic composition)

 Purpose:          Implementation of the set-palette class which extends the
                   palette class by simply instantiating the sets given in
                   the palette.  

                   Note that the sets in this palette may refer to
                   previously defined sets in order to obviate retyping note
                   lists.  Hence the reference to bcl-chord2 in the
                   bcl-chord3 set of the example below will instantiate a
                   set based on a transposed clone of that set previously
                   stored as bcl-chord2.  

                     (make-set-palette 
                      'test
                      '((bcl-chord1
                         ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5
                               dqf5 gs5 b5) 
                          :subsets
                          ((tc1 (ds2 e3 a4))
                           (tc2 (bf1 d4 cqs5))
                           (qc1 (aqf2 e3 a4 dqf5 b5))
                           (qc2 (bf1 c3 gqs3 cs4 cqs5)))
                          :related-sets
                          ((missing (bqs0 eqs1 f5 aqs5 eqf6 fqs6 
                                          bqf6 dqs7 fs7)))))
                        (bcl-chord2
                         ((bf1 d2 fqf2 fqs2 b2 c3 f3 g3 bqf3 bqs3 fs4 gs4 a4
                           cs5 gqf5) 
                          :subsets
                          ((tc1 (d2 g3 cs5))
                           (tc2 (eqs2 f3 bqf3))
                           (qc1 (eqs2 c3 f3 fs4 gqf5))
                           (qc2 (d2 fqs2 bqs3 gs4 a4)))
                          :related-sets
                          ((missing (aqs0 dqs1 ds5 gqs5 dqf6 eqf6 aqf6 cqs7
                                          e7))))) 
                        (bcl-chord3 
                         (bcl-chord2 :transposition 13))))


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

 Creation date:    August 14th 2001

 $$ Last modified:  20:22:55 Mon Aug 19 2024 CEST

 SVN ID: $Id$

set-palette/add-harmonics [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Add harmonically-related pitches to each set in the palette. See the sc-set
 class method for details and the get-harmonics function (utilities.lsp) for
 keyword arguments.

SYNOPSIS

(defmethod add-harmonics ((sp set-palette) &rest keywords)

set-palette/auto-sequence [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 July 30th 2015, Edinburgh

DESCRIPTION

 Automatically create an ordering for the sets in a set-palette based on a
 dissonance envelope and a spectral centroid envelope. For a description of
 a set or chord's dissonance or spectral centroid see the
 calculate-spectral-centroid and calculate-dissonance methods in the chord
 class.

 The envelopes describe a desired general tendency to, for example, proceed
 from less dissonant to more dissonant sets as the ordering (sequence) of
 sets proceeds. Such an envelope would move from lower to higher
 values. Similarly with the spectral centroid envelope: moving from a lower
 to a higher value implies moving from chords with an overall lower pitch
 height to chords with a higher pitch height.

 The envelopes should be expressed over any X axis range but with a Y axis
 range of 0.0 to 1.0 only. The x-axes will be stretched to fit over the
 number of sets in the palette. The Y axes will be stretched to fit the
 range of dissonance and centroid values to be found in the sets in the
 palette (see the quality-extremes method).

 The default method is successive. It selects sets one-by-one via a sort
 function which compares the sets' characteristics to those of the current
 envelope values. Essentially, when we are comparing two sets via the sort
 function, we look at the deviation between the sets' dissonance values and
 the current desired dissonance value from the envelope, similarly with the
 spectral centroid.  The chord with the smallest combined deviation will be
 chosen first. If either envelope is nil, then the sorting is based on the
 other envelope only. Similarly, weighting factors of any arbitrary positive
 number can be passed via :dissonance-weight and :centroid-weight to
 emphasise or deemphasise these properties when sorting. Higher values will
 mean that that property will take precedence over the other property.
 
 An alternative method, indicated by :permutate T, is to get all (or at
 least a lot of) permutations of the sets in the palette and then score each
 ordering against the curves, as a form of fitness test. The advantage of
 this approach is that the best solution overall can be found. The
 successive approach, on the other hand will find the best fit at the
 beginning of the process but as it proceeds along the envelope and we run
 out of sets to select from, the fit can become worse and worse.

 In any case there is no guarantee that the desired curves will be expressed
 exactly in the returned ordering. The function tries to find the best fit
 but success depends very much on the number and variety of sets in the
 palette. 

 Also taken into account when in both methods is the lowest note of the
 set. If :repeating-bass is NIL (the default) then the function tries to
 avoid repeating bass notes in two consecutive sets. Repeating highest notes
 are allowed.
 
 NB Unlike the chord methods which calculate dissonance and spectral
 centroid, there is no way to pass spectral data here. If you want to
 override the default spectral data then use (set-sc-config 'default-spectra
 ...). See globals.lsp for more details.

ARGUMENTS

 - the set-palette object

OPTIONAL ARGUMENTS

 keyword arguments:
 - dissonance-env: The desired dissonance envelope. Y values: 0.0 to 1.0
   Default '(0 .1 62 1 100 .3)
 - centroid-env:  The desired spectral centroid envelope.Y values: 0.0 to 1.0
   Default '(0 .4 62 1 100 .2) 
 - dissonance-weight: A weighting factor (scaler) applied to
   dissonance. Higher values result in dissonance playing a larger role in
   the decision process. Default 1.0
 - centroid-weight: a similar factor for spectral centroid. Default 1.0
 - verbose:  Whether to print data as the decision process proceeds.
   Default NIL 
 - repeating-bass: Whether to allow bass notes to repeat between two
   consecutive chords. Default NIL
 - silent: Whether to print warnings or not. Default NIL
 - map-section: if you want a list of references suitable to be passed
   as a set-map, set this keyword to the integer ID of the section the map
   will be used for. Default = NIL.
 - permutate: use the permutation rather than the successive approach. This
   can either be T (which will limit to 2000), 'all (get all
   permutations--could take a very long time), or an integer to represent
   the maximum number of permutations we'll try. Default = NIL.

RETURN VALUE

 If we're using the permutate method then a single list of the sets'
 set-palette references is returned. If we're using the successive method we
 return two values: A list of the full references of the sets in the set
 palette in the automatically determined order, along with a list of the
 deviations from the ideal this order represents. Either method might return
 a list suitable for passing to a set-map (see example below).

EXAMPLE

(auto-sequence
 (recursive-set-palette-from-ring-mod '(a4 b4) 'spfrm-test
                                      :warn-no-bass nil)
 :verbose nil :centroid-weight 2 :silent t)
=>
((A4 15) (A4 13) (A4 4) (A4 7) (B4 4) (A4 14) (A4 2) (A4 20) (B4 2) (B4 17)
 (B4 14) (B4 11) (B4 9) (A4 12) (B4 21) (B4 6) (A4 6) (B4 5) (B4 7) (B4 12)
 (A4 19) (A4 5) (A4 9) (A4 3) (A4 11) (A4 10) (B4 18) (B4 10) (B4 16) (B4 3)
 (B4 19) (A4 17) (B4 13) (A4 8) (B4 15) (B4 8) (B4 20) (B4 1) (A4 21) (A4 1)
 (A4 18) (A4 16))
((0.3433064594719475d0 0.04460029910249326d0 0.38790675857444074d0)
 (0.36511199730074173d0 0.10718227303159739d0 0.4722942703323391d0)
...

(auto-sequence
 (recursive-set-palette-from-ring-mod '(a4 b4) 'spfrm-test
                                      :warn-no-bass nil)
 :verbose nil :centroid-weight 2 :silent t :permutate t :map-section 1)
=>
((1
  ((B4 1) (B4 3) (B4 15) (B4 5) (B4 10) (A4 3) (A4 17) (A4 1) (A4 14) (A4 15)
   (B4 12) (A4 4) (B4 2) (B4 18) (A4 20) (A4 5) (B4 4) (B4 6) (B4 20) (B4 17)
   (B4 16) (B4 11) (A4 6) (B4 9) (A4 7) (A4 12) (B4 21) (A4 18) (A4 19) (A4 13)
   (B4 19) (B4 7) (A4 16) (B4 13) (A4 8) (A4 2) (B4 8) (A4 9) (A4 10) (A4 11)
   (A4 21) (B4 14))))

SYNOPSIS

(defmethod auto-sequence ((sp set-palette)
                          &key
                            (dissonance-env '(0 .1 62 1 100 .3))
                            (centroid-env '(0 .4 62 1 100 .2))
                            (dissonance-weight 1.0)
                            (centroid-weight 1.0)
                            map-section permutate verbose repeating-bass silent)

set-palette/calculate-spectral-centroid [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 January 30th 2016

DESCRIPTION

 Calculate the spectral centroid values for each set in a set-palette. This
 will set the centroid slot of each set. 

ARGUMENTS

 - a set-palette object

OPTIONAL ARGUMENTS

 keyword arguments:
 - sort: If T, sorts the list values from high to low, otherwise the list
   will be returned with the order of the sets in the palette. Default =
   NIL. 
 see this method in the chord class for a description of further keywords

RETURN VALUE

 a list of two-element lists: the reference to the set within the palette
 and the centroid value.

SYNOPSIS

(defmethod calculate-spectral-centroid ((sp set-palette)
                                        &rest keyargs &key &allow-other-keys)

set-palette/cmn-display [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Generate printable music notation output (.EPS) of the given set-palette
 object, including separate notation of the SUBSETS and RELATED-SETS slots,
 using the Common Music Notation (CMN) interface. The method requires at
 least the name of the given set-palette object, but has several additional
 optional arguments for customizing output.

 NB: Some of the keyword arguments are CMN attributes and share the same
     name as the CMN feature they effect.

ARGUMENTS

 - A set-palette object.

OPTIONAL ARGUMENTS

 keyword arguments:
 - :file. The file path, including the file name, of the file to be
   generated.
 - :4stave. T or NIL to indicate whether the note-heads of the output should
   be printed on 4 staves (or 2). T = 4. Default = NIL.
 - :text-x-offset. Number (positive or negative) to indicate the horizontal
   offset of any text in the output. A value of 0.0 results in all text
   being lined up left-flush with the note-heads below it. Units here and
   below are relative to CMN staff size. Default = -0.5. 
 - :text-y-offset. Number (positive or negative) to indicate the vertical
   offset of any text in the output.
 - :font-size. A number indicating the size of any text font used in the
   output. This affects text only and not the music (see :size below for
   changing the size of the music). If 0 then no text will be
   displayed. Default = 10.0.
 - :break-line-each-set. T or NIL to indicate whether each set-palette
   object should be printed on a separate staff or consecutively on the same
   staff. T = one staff per set-palette object. Default = T.
 - :line-separation. A number to indicate the amount of white space between
   lines of music (systems), measured as a factor of the staff
   height. Default = 3. This is a direct CMN attribute.
 - :staff-separation. A number to indicate the amount of white space between
   staves belong to the same system, measured as a factor of the staff
   height. Default = 3. This is a direct CMN attribute.
 - :transposition. Nil or a number (positive or negative) to indicate the
   number of semitones by which the pitches of the given set-palette object
   should be transposed before generating the CMN output. Default = NIL (0).
 - :size. A number to indicate the size of the music-font in the CMN
   output. This affects music only, not text.
 - :use-octave-signs. T or NIL to indicate whether to automatically insert
   ottava spanners. Automatic placement depends on the overall pitch
   content. This is a slippery-chicken process and may produce different
   results than :automatic-octave-signs, which is a direct CMN process. 
   T = insert octave signs. Default = NIL.
 - :automatic-octave-signs. T or NIL to indicate whether to automatically
   insert ottava spanners. Automatic placement depends on the overall pitch
   content. This is a direct CMN process and may produce different results
   than :use-octave-signs, which is a slippery-chicken process. T = insert
   octave signs. Default = NIL.
 - :include-missing-chromatic. T or NIL to indicate whether to also print
   any chromatic pitches from the complete-set that are not present in the
   given set-palette object. T = print. Default = T.
 - :include-missing-non-chromatic. T or NIL to indicate whether to also
   print any microtonal pitches from the complete-set that are not
   present in the given set-palette object. T = print.  Default = T.

RETURN VALUE

 T

EXAMPLE

;; A typical example with some specified keyword values for file, font-size,
;; break-line-each-set, size, include-missing-chromatic and
;; include-missing-non-chromatic 
(let ((msp (make-set-palette 
            'test
         p   '((1 ((1
                   ((c3 g3 cs4 e4 fs4 a4 bf4 c5 d5 f5 gf5 af5 ef6)))
                  (2
                   ((c3 g3 cs4 e4 fs4 a4 bf4 c5 d5 f5 gf5 af5 ef6)
                    :subsets
                    ((tc1 (d2 g3 cs5))
                     (tc2 (eqs2 f3 bqf3))
                     (tc3 (b2 bqs3 gqf5)))))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (cmn-display msp
               :file "/tmp/sp-output.eps"
               :font-size 8
               :break-line-each-set nil
               :size 10
               :include-missing-chromatic nil
               :include-missing-non-chromatic nil))

SYNOPSIS

(defmethod cmn-display ((sp set-palette) &rest keyargs &key &allow-other-keys)

set-palette/find-sets-with-pitches [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Return a list of sets (as complete-set objects) from a given set-palette
 object based on whether they contain specified pitches.

 NB: Only sets which contain all of the specified pitches will be returned. 

ARGUMENTS

 - A set-palette object.
 - A list of pitches, either as pitch objects or note-name symbols.

 OPTION ARGUMENTS
 - T or NIL to indicate whether to print the notes of each successful set as
   they are being examined.

RETURN VALUE

 A list of complete-set objects.

EXAMPLE

;; Find sets that contain a single pitch
(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((g3 c4 e4 g4)))
                  (2
                   ((c4 d4 e4 g4)))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (find-sets-with-pitches msp '(c4)))

=>
(
COMPLETE-SET: complete: NIL
[...]
data: (BF3 C4 D4 F4)
[...]
COMPLETE-SET: complete: NIL
[...]
data: (C4 F4 A4 C5)
[...]
COMPLETE-SET: complete: NIL
[...]
data: (C4 D4 E4 G4)
[...]
COMPLETE-SET: complete: NIL
[...]
data: (G3 C4 E4 G4)
)

;; Search for a set of two pitches, printing the successfully matched sets
(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((g3 c4 e4 g4)))
                  (2
                   ((c4 d4 e4 g4)))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (print (find-sets-with-pitches msp '(c4 f4) t)))

=>
(2 1): (C4 F4 A4 C5)
(3 2): (BF3 C4 D4 F4)
(
COMPLETE-SET: complete: NIL
[...]
data: (BF3 C4 D4 F4)
COMPLETE-SET: complete: NIL
[...]
data: (C4 F4 A4 C5)
)

SYNOPSIS

(defmethod find-sets-with-pitches ((sp set-palette) pitches &optional print)

set-palette/force-micro-tone [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Change the value of the MICRO-TONE slot of all pitch objects in a given
 set-palette object to the specified <value>. NB If the pitches are
 microtonal and thus have associated pitch-bends and microtonal frequencies,
 these will not be changed, i.e. only the micro-tone slot is changed. 

ARGUMENTS

 - A set-palette object.

OPTIONAL ARGUMENTS

 - An item of any type that is to be the new value of the MICRO-TONE slot of
   all pitch objects in the given sc-set object (generally T or
   NIL). Default = NIL. 

RETURN VALUE

 Always returns T.

EXAMPLE

;; Create a set-palette object whose individual sets contain some micro-tones
;; and print the contents of all the MICRO-TONE slots to see the values. Then
;; apply the force-micro-tone method and print the slots again to see the
;; changes. 

(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5 dqf5 gs5 
                         b5)))
                  (2
                   ((bf1 d2 fqf2 fqs2 b2 c3 f3 g3 bqf3 bqs3 fs4 gs4 a4 cs5 gqf5)
                    :subsets
                    ((tc1 (d2 g3 cs5))
                     (tc2 (eqs2 f3 bqf3))
                     (tc3 (b2 bqs3 gqf5)))))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (print (loop for i in (data msp) 
            collect (loop for j in (data (data i))
                       collect (loop for p in (data j)
                                  collect (micro-tone p)))))
  (force-micro-tone msp t)
  (print (loop for i in (data msp) 
            collect (loop for j in (data (data i))
                       collect (loop for p in (data j)
                                  collect (micro-tone p))))))

=>
(((NIL NIL T NIL NIL T T NIL NIL NIL NIL T T NIL NIL)
  (NIL NIL T T NIL NIL NIL NIL T T NIL NIL NIL NIL T))
 ((NIL NIL T NIL NIL T T NIL NIL NIL NIL T T NIL NIL)
  (NIL NIL T T NIL NIL NIL NIL T T NIL NIL NIL NIL T))
 ((NIL NIL T NIL NIL T T NIL NIL NIL NIL T T NIL NIL)
  (NIL NIL T T NIL NIL NIL NIL T T NIL NIL NIL NIL T)))

(((T T T T T T T T T T T T T T T) (T T T T T T T T T T T T T T T))
 ((T T T T T T T T T T T T T T T) (T T T T T T T T T T T T T T T))
 ((T T T T T T T T T T T T T T T) (T T T T T T T T T T T T T T T)))

SYNOPSIS

(defmethod force-micro-tone ((sp set-palette) &optional value)

set-palette/gen-max-coll-file [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 26-Dec-2009

DESCRIPTION

 Write a text file from a given set-palette object suitable for reading into
 Max/MSP's coll object. The resulting text file has one line for each set in
 the palette, with the coll index being the ID of the set. The rest of the
 line is a list of frequency/amplitude pairs (or MIDI note number/velocity if
 required). 0.1 is the default amplitude for frequencies; 80 the default
 velocity for MIDI; if 'transp is the format argument then no amplitude or
 velocity data is written.

ARGUMENTS

 - A set-palette object.
 - The name (and path) of the .txt file to write.

OPTIONAL ARGUMENTS

 - 'freq, 'freq-only (no amplitudes), 'midi', or 'transp to indicate whether
   frequencies in Hertz, MIDI note numbers, or semitone transposition factors
   should be generated. If the latter then the middle note will be
   represented by 0 transposition.  Default = 'freq (frequencies).
 - a list of references into the palette to define the order in which the
   sets are written. Default = NIL = sets will be written in the order in
   which they appear in the palette.
 - T or NIL to indicate whether successive integers should be used as indices
   in the coll. Default = NIL = use combined set-palette and set IDs.

RETURN VALUE

EXAMPLE

;; Generates frequencies by default
(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((g3 c4 e4 g4)))
                  (2
                   ((c4 d4 e4 g4)))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (gen-max-coll-file msp "/tmp/msp-mcf.txt"))

;; Set the optional argument to 'midi to generate MIDI note numbers instead
(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((g3 c4 e4 g4)))
                  (2
                   ((c4 d4 e4 g4)))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (gen-max-coll-file msp "/tmp/msp-mcf.txt" 'midi))

SYNOPSIS

(defmethod gen-max-coll-file ((sp set-palette) file &optional
                                                      (format 'freq)
                                                      refs ints)

set-palette/gen-midi-chord-seq [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Generate a MIDI file in which each set of the given set-palette object is
 played at 1 second intervals.

ARGUMENTS

 - A set-palette object.
 - The name and path for the MIDI file to be generated.

OPTIONAL ARGUMENTS

 - the tempo in beats per minute. Default = 60.
 - subsets-id, related-sets-id. If you want to generate a MIDI file of just
   a named subset or related-set, pass the ID here. NB this ID will have to
   exist for all sets.

RETURN VALUE

 Always returns T

EXAMPLE

(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5 dqf5 gs5
                         b5))) 
                  (2
                   ((bf1 d2 fqf2 fqs2 b2 c3 f3 g3 bqf3 bqs3 fs4 gs4 a4 cs5 gqf5)
                    :subsets
                    ((tc1 (d2 g3 cs5))
                     (tc2 (eqs2 f3 bqf3))
                     (tc3 (b2 bqs3 gqf5)))))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (gen-midi-chord-seq msp "/tmp/msp-gmchs.mid"))

SYNOPSIS

(defmethod gen-midi-chord-seq ((sp set-palette) midi-file
                               &optional (tempo 60.0)
                                 subsets-id related-sets-id)

set-palette/limit [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Limit all the sets in a palette to a specified range. See the tl-set class
 limit method for details of the this method and its arguments.

RETURN VALUE

 The set-palette object.

SYNOPSIS

(defmethod limit ((sp set-palette) &key upper lower do-related-sets)

set-palette/limit-shift-octave [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 19th August 2015, Edinburgh

DESCRIPTION

 Apply the tl-set method of the same name to each set in the palette. See
 that class method description for details. 

ARGUMENTS

 - the set-palette object

OPTIONAL ARGUMENTS

 See descriptions in tl-set limiti-shift-octave method noting that here the
 :upper and :lower arguments can be a single note symbol or pitch object, as
 in tl-set, or an envelope. In the latter case, the x axis can be over any
 arbitrary scale and the y values can either be note symbols or midi note
 numbers. 

RETURN VALUE

 The set-palette object (modified).

SYNOPSIS

(defmethod limit-shift-octave ((sp set-palette) &key upper lower
                                                  do-related-sets)

set-palette/make-set-palette [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Create a set-palette object.

 Note that the sets in this palette may refer to previously defined sets in
 order to avoid retyping note lists (see example below).

ARGUMENTS

 - A symbol that is to be the ID of the resulting set-palette object.
 - A recursive list of key/data pairs, of which the deepest level of data
   will be a list of note-name symbols.

OPTIONAL ARGUMENTS

 keyword arguments:
 - :recurse-simple-data. T or NIL to indicate whether to interpret
   two-element data lists as recursive palettes. Default = T.
 - :warn-note-found. T or NIL to indicate whether to print warnings when
   specified data is not found with subsequent calls to the get-data method.

RETURN VALUE

 A set-palette object.

EXAMPLE

;;; Create a set-palette object
(make-set-palette 
 'test
 '((1 ((1
        ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5 dqf5 gs5 b5)
         :subsets
         ((tc1 ((ds2 e3 a4) "a-tag"))
          (tc2 (bf1 d4 cqs5))
          (tc3 (c3 cs4 gs5)))))
       (2
        ((bf1 d2 fqf2 fqs2 b2 c3 f3 g3 bqf3 bqs3 fs4 gs4 a4 cs5 gqf5)
         :subsets
         ((tc1 (d2 g3 cs5))
          (tc2 (eqs2 f3 bqf3))
          (tc3 (b2 bqs3 gqf5)))))
       (3
        ((cqs2 fs2 g2 c3 d3 fqs3 gqf3 cs4 ds4 e4 gs4 dqf5 f5 a5 bqs5)
         :subsets
         ((tc1 (cqs2 c3 f5))
          (tc2 (fs2 e4 bqs5))
          (tc3 (d3 ef4 a5)))))))
   (2 ((1 ((1 1) :transposition 5))
       (2 ((1 2) :transposition 5))
       (3 ((1 3) :transposition 5))))
   (3 ((1 ((1 1) :transposition -2))
       (2 ((1 2) :transposition -2))
       (3 ((1 3) :transposition -2))))))

=>
SET-PALETTE: 
PALETTE: 
RECURSIVE-ASSOC-LIST: recurse-simple-data: T
                      num-data: 9
                      linked: NIL
                      full-ref: NIL
ASSOC-LIST: warn-not-found T
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 3, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: TEST, tag: NIL, 
data: (
[...]

;;; NB A simple list of sets (with unique id slots) can also be passed.

;;; Create a set-palette object by referencing a set-palette-object already
;;; defined (sp1) and transposing a clone of that object.
(make-set-palette 
 'test
 '((sp1
    ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5
          dqf5 gs5 b5) 
     :subsets
     ((tc1 (ds2 e3 a4))
      (tc2 (bf1 d4 cqs5))
      (qc1 (aqf2 e3 a4 dqf5 b5))
      (qc2 (bf1 c3 gqs3 cs4 cqs5)))
     :related-sets
     ((missing (bqs0 eqs1 f5 aqs5 eqf6 fqs6 
                     bqf6 dqs7 fs7)))))
   (sp2
    (sp1 :transposition 13))))

=>
SET-PALETTE: 
PALETTE: 
RECURSIVE-ASSOC-LIST: recurse-simple-data: T
                      num-data: 2
                      linked: NIL
                      full-ref: NIL
ASSOC-LIST: warn-not-found T
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 2, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: TEST, tag: NIL, 
data: (
COMPLETE-SET: complete: NIL
              num-missing-non-chromatic: 7
              num-missing-chromatic: 2
              missing-non-chromatic: (BQS BQF AQS FQS EQS EQF DQS)
              missing-chromatic: (FS F)
[...]
    subsets: 
TC1: (DS2 E3 A4)
TC2: (BF1 D4 CQS5)
QC1: (AQF2 E3 A4 DQF5 B5)
QC2: (BF1 C3 GQS3 CS4 CQS5)
    related-sets: 
MISSING: (BQS0 EQS1 F5 AQS5 EQF6 FQS6 BQF6 DQS7 FS7)
SCLIST: sclist-length: 15, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: SP1, tag: NIL, 
data: (BF1 EF2 AQF2 C3 E3 GQF3 GQS3 CS4 D4 G4 A4 CQS5 DQF5 GS5 B5)
[...]
COMPLETE-SET: complete: NIL
              num-missing-non-chromatic: 7
              num-missing-chromatic: 2
              missing-non-chromatic: (BQS BQF AQS FQS EQS EQF DQS)
              missing-chromatic: (FS F)
TL-SET: transposition: 13
        limit-upper: NIL
        limit-lower: NIL
[...]
    subsets: 
TC1: (E3 F4 BF5)
TC2: (B2 EF5 DQF6)
QC1: (AQS3 F4 BF5 DQS6 C7)
QC2: (B2 CS4 AQF4 D5 DQF6)
    related-sets: 
MISSING: (BQS0 EQS1 F5 AQS5 EQF6 FQS6 BQF6 DQS7 FS7)
SCLIST: sclist-length: 15, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: SP2, tag: NIL, 
data: (B2 E3 AQS3 CS4 F4 GQS4 AQF4 D5 EF5 AF5 BF5 DQF6 DQS6 A6 C7)
**************
)

SYNOPSIS

(defun make-set-palette (id palette 
                         &key (recurse-simple-data t) (warn-not-found t))

set-palette/midi-play [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 25th May 2017, Edinburgh

DESCRIPTION

 Write a MIDI file containing the sets in the set-palette

ARGUMENTS

 - the set-palette object

OPTIONAL ARGUMENTS

 keyword arguments:
 - :midi-file. The path (string) of the midi file to write. Default is to
   use the ID of the set-palette and write it into the default directory.
 - :tempo. The tempo of the MIDI file in beats per minute. Default = 60.
 - :auto-open. Whether to open the midi file after generating (not available
   on all operating systems). Default is (get-sc-config
   'midi-play-auto-open) which itself defaults to sc-auto-open in the
   *features* list.
 - :related-sets-id :subsets-id. If you want to generate a MIDI file of just
   a named subset or related-set, pass the ID here. NB this ID will have to
   exist for all sets.

RETURN VALUE

 T

SYNOPSIS

(defmethod midi-play ((sp set-palette)
                      &key
                        (tempo 60.0)
                        (auto-open (get-sc-config 'midi-play-auto-open))
                        ;; MDE Sat Mar 20 12:05:17 2021, Heidhausen
                        related-sets-id subsets-id
                        (midi-file
                         (format nil "~a~a.mid"
                                 (get-sc-config 'default-dir)
                                 (string-downcase (string (id sp))))))

set-palette/quality-extremes [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Get the extremes (as four values) of the dissonance (min max) and spectral
 centroid (min max) of a whole set palette.

ARGUMENTS

 - a set-palette object

RETURN VALUE

 Four values (i.e. to be used by multiple-value-bind and friends):
 dissonance min, dissonance max, centroid min, centroid max. 

SYNOPSIS

(defmethod quality-extremes ((sp set-palette))

set-palette/recursive-set-palette-from-ring-mod [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Create a set-palette object consisting of sub palette-objects whose pitch
 content is generated based on ring modulation routines applied to the
 specified pitches.

ARGUMENTS

 - A list of note-name symbols, each of which will serve as the reference
   pitch from which a new set-palette object is made using the
   set-palette-from-ring-mod method.
 - A symbol that will be the ID for the top-level set-palette object. The
   IDs of the new set-palette objects contained in the top-level object are
   generated from the note-name symbols of the reference-pitches, with the
   IDs of the pitch sets contained with them then generated by sequential
   numbers.

OPTIONAL ARGUMENTS

 keyword arguments:
 - :partials. A list of integers that are the partials which the method is
   to ring modulate, with 1 being either the reference-note or the bass note
   that would have the reference-note as the highest partial in the given
   list. Default = '(1 3 5 7).
 - :warn-no-bass. T or NIL to indicate whether to issue a warning when
   ring-mod-bass fails to find suitable bass notes for the generated sets. T
   = warn. Default = T.
 - :do-bass. T or NIL to indicate whether to add notes created by the
   ring-mod-bass function to the resulting set-palette object. T = create and
   add bass notes. Default = T.
 - :remove-octaves. T or NIL to indicate whether to remove the upper
   instances of any octave-equivalent pitches from the resulting set-palette
   object. T = remove. Default = NIL.
 - :min-bass-notes. An integer that is the minimum number of bass notes to
   be generated and added to the resulting set-palette object. Default = 1.
 - :ring-mod-bass-octave. An integer that is the MIDI octave reference
   number (such as the 4 in 'C4), indicating the octave from which the bass
   note(s) are to be taken.
 - :force-chromatic. T or NIL. If T, force all micro-tone slots of pitch objects
   to be NIL so that they won't be filtered out when a set is to be used by a
   chromatic instrument. See sc-set class force-micro-tone for more details.

RETURN VALUE

 - A set-palette object (recursive)

EXAMPLE

;; Simple useage with default keyword argument values
(recursive-set-palette-from-ring-mod '(a4 b4 c4) 'rspfrm-test)

=>
SET-PALETTE: 
PALETTE: 
RECURSIVE-ASSOC-LIST: recurse-simple-data: T
                      num-data: 3
                      linked: NIL
                      full-ref: NIL
ASSOC-LIST: warn-not-found T
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 3, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: RSPFRM-TEST, tag: NIL, 
data: (
NAMED-OBJECT: id: A4, tag: NIL, 
data: 
SET-PALETTE: 
PALETTE: 
RECURSIVE-ASSOC-LIST: recurse-simple-data: T
                      num-data: 21
                      linked: NIL
                      full-ref: NIL
ASSOC-LIST: warn-not-found T
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 21, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: A4, tag: NIL, 
data: (
COMPLETE-SET: complete: NIL
[...]

SYNOPSIS

(defun recursive-set-palette-from-ring-mod (reference-notes id
                                            &key
                                              (warn-no-bass t)
                                              (ring-mod-bass-octave 0)
                                              (do-bass t)
                                              remove-octaves
                                              force-chromatic
                                              (min-bass-notes 1)
                                              (partials '(1 3 5 7)))

set-palette/remove-similar [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 12th August 2015, Wals, Austria

DESCRIPTION

 Remove similar sets from a palette when two sets are deemed
 similar. The set furthest down the data list will remain, whatever the
 ID. Note that this is a destructive operation.

 We use the similarity chord method to remove sets from the palette, so see
 that method for further information and for more keyword argument
 descriptions.

ARGUMENTS

 - the set-palette object

OPTIONAL ARGUMENTS

 keyword arguments:
 - :threshold. The lowest value that the chord class's similarity method may
    return in order to trigger removal. Default = 0.8
 - :clone. Whether to clone the set-palette object before removing sets.
 - :enharmonics-are-equal. See similarity method. Default = T.
 - :octaves-are-true. See similarity method. Default = NIL.

RETURN VALUE

 the pared-down set-palette object

SYNOPSIS

(defmethod remove-similar ((sp set-palette) &key (threshold 0.8)
                                              (clone nil)
                                              (enharmonics-are-equal t)
                                              (octaves-are-true nil))

set-palette/ring-mod [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Ring modulate (sum and difference tones) two pitches and return the
 resulting pitch and harmonic partials thereof.

ARGUMENTS

 - A first pitch, either as a numeric hertz frequencey or a note-name
   symbol.  
 - A second pitch, either as a numeric hertz frequencey or a note-name
   symbol. The second value needn't be higher than first.

OPTIONAL ARGUMENTS

 keyword arguments
 - :return-notes. T or NIL to indicate whether to return the results as
   note-name symbols or frequency numbers. T = note-name symbols. 
   Default = NIL.
 - :pitch1-partials. An integer that indicates how many harmonic partials of
   the first pitch are to be included in the modulation. Default = 3.
 - :pitch2-partials. An integer that indicates how many harmonic partials of
   the second pitch are to be included in the modulation. Default = 2.
 - :min-freq. A number that is the the minimum frequency (hertz) that may be
   returned. Default = 20.
 - :max-freq. A number that is the the maximum frequency (hertz) that may be
   returned. Default = 20000.
 - :round. T or NIL to indicate whether frequency values returned are first
   rounded to the nearest hertz. T = round. Default = T
 - :remove-duplicates. T or NIL to indicate whether any duplicate
   frequencies are to be removed from the resulting list before returning
   it. T = remove. Default = T.
 - :print. T or NIL to indicate whether resulting data is to be printed as
   it is being generated. T = print. Default = NIL.
 - :remove-octaves. T or NIL to indicate whether octave repetitions of
   pitches will be removed from the resulting list before returning it,
   keeping only the lowest instance of each pitch. This argument can also be
   set as a number or a list of numbers that indicates which octave
   repetitions will be allowed, the rest being removed. For example,
   :remove-octaves '(1 2) will remove all octave repetitions of a given
   pitch except for those that are 1 octave and 2 octaves above the given
   pitch; thus '(c1 c2 c3 c4 c5) would return '(c1 c2 c3), removing c4 and
   c5. Default = NIL.
 - :scale. A variable that indicates which scale to use when converting
   frequencies to note-names. Default = cm::*scale* i.e. the value to which
   the Common Music scale is set, which in slippery chicken is
   *quarter-tone* by default.

RETURN VALUE

 A list of note-name symbols or frequencies.

EXAMPLE

;; Apply ring modulation to 'C4 and 'D4, using 5 partials of the first pitch
;; and 3 partials of the second, removing octave repetitions, and returning the
;; results as rounded hertz-frequencies
(ring-mod 'c4 'd4
          :pitch1-partials 5
          :pitch2-partials 3
          :min-freq 60
          :max-freq 2000
          :remove-octaves t)

=> (64.0 96.0 166.0 198.0 230.0 358.0 427.0 459.0 491.0 555.0 619.0 817.0
    1079.0 1143.0 1340.0 1372.0 1404.0 1666.0 1895.0 1927.0)

;; Applying ring modulation to two frequencies, returning the results as
;; note-name symbols within the chromatic scale.
(ring-mod '261.63 '293.66 
          :return-notes t
          :remove-duplicates nil
          :scale cm::*chromatic-scale*)

=> (C1 C2 G3 BF3 E4 B4 CS5 AF5 AF5 CS6 CS6 F6)

SYNOPSIS

(defun ring-mod (pitch1 pitch2 ;; hertz or notes
                 &key (return-notes nil) (pitch1-partials 3) (pitch2-partials 2)
                 (min-freq 20) (max-freq 20000) (round t) (remove-duplicates t)
                 (print nil) remove-octaves (scale cm::*scale*))

set-palette/ring-mod-bass [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Using ring-modulation techniques, invent (sensible) bass note(s) from a
 list of frequencies.  

ARGUMENTS

 - A list of numbers that are hertz frequencies from which the bass note(s)
   are to be generated.

OPTIONAL ARGUMENTS

 keyword arguments
 - :bass-octave. An integer that is an octave indicator (e.g. the 4 in
   'C4). The method will only return any frequencies/note-names generated
   that fall in this octave. Default = 0.
 - :low. A note-name symbol that is the lowest possible pitch of those
   returned. This argument further restricts the :bass-octave argument. Thus
   a :bass-octave value of 1 could be further limited to no pitches below
   :low 'DS1. Default = 'A0.
 - :high. A note-name symbol that is the highest possible pitch of those
   returned. This argument further restricts the :bass-octave argument. Thus
   a :bass-octave value of 1 could be further limted to no pitches above
   :high 'FS1. Default = 'G3.
 - :round. T or NIL to indicate whether the frequencies returned are rounded
   to integer values. T = round. Default = T.
 - :warn. T or NIL to print a warning when no bass can be created from the
   specified frequencies/note-names. T = print warning. Default = T.
 - :return-notes. T or NIL to indicate whether the resulting pitches should
   be returned as note-names instead of frequencies. T = return as
   note-names. Default = NIL.
 - :scale. A variable pointing to the scale to which any translation of
   frequencies into note-names symbols should take place. By default this
   value is set to cm::*scale*, which is automatically set by slippery
   chicken to 'quarter-tone at initialisation. To return e.g. pitches rounded
   to chromatic note-names set this argument to cm::*chromatic-scale*.

RETURN VALUE

 Returns a list of frequencies by default.

 Setting the :return-notes keyword argument to T will cause the method to
 return note-name symbols instead.

EXAMPLE

;; Simple usage with default keyword argument values
(ring-mod-bass '(261.63 293.66 329.63 349.23))

=> (28 29 32)

;; Return as note-names instead, in quarter-tone scale by default
(ring-mod-bass '(261.63 293.66 329.63 349.23)
               :return-notes t)

=> (A0 BF0 BQS0) 

;; Set the :scale argument to cm::*chromatic-scale* to return equal-tempered
;; note-name symbols instead
(ring-mod-bass '(261.63 293.66 329.63 349.23)
               :return-notes t
               :scale cm::*chromatic-scale*)

=> (A0 BF0 C1)

;; Return pitches from bass octave 1 rather than default 0
(ring-mod-bass '(261.63 293.66 329.63 349.23 392.00)
               :return-notes t
               :scale cm::*chromatic-scale*
               :bass-octave 1)

=> (CS1 D1 F1 G1 A1 B1)

;; Further limit the notes returned by setting :low and :high values
(ring-mod-bass '(261.63 293.66 329.63 349.23 392.00)
               :return-notes t
               :scale cm::*chromatic-scale*
               :bass-octave 1
               :low 'e1
               :high 'a1)

=> (F1 G1)

;; Set the :round argument to NIL to return decimal-point frequencies
(ring-mod-bass '(261.63 293.66 329.63 349.23 392.00)
               :bass-octave 1
               :low 'e1
               :high 'a1
               :round NIL)

=> (42.76999999999998 43.45666666666667 43.80000000000001 49.16999999999999)

;; The method prints a warning by default if no bass note can be made
(ring-mod-bass '(261.63))

=>
NIL
WARNING: set-palette::ring-mod-bass: can't get bass from (261.63)!

;; This warning can be suppressed by setting the :warn argument to NIL
(ring-mod-bass '(261.63) :warn nil)

=> NIL

SYNOPSIS

(defun ring-mod-bass (freqs &key (bass-octave 0) (low 'a0) (high 'g3) (round t)
                      (warn t) (return-notes nil) (scale cm::*scale*))

set-palette/round-to-nearest [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 January 30th 2017

DESCRIPTION

 Rounds all pitch objects to the nearest pitch in the current or given
 scale. See also sc-set, chord, slippery-chicken, event, and pitch class
 methods.  

ARGUMENTS

 - a set-palette object

OPTIONAL ARGUMENTS

 keyword argument:
 :scale. The scale to use when rounding. (Common Music tuning object or
 symbol). If a symbol, then 'chromatic-scale, 'twelfth-tone, or 'quarter-tone
 only at present. Default is the current scale as set by (in-scale :...).

RETURN VALUE

 the modified set-palette

SYNOPSIS

(defmethod round-to-nearest ((sp set-palette) &key (scale cm::*scale*))

set-palette/set-palette-from-ring-mod [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Create a new set-palette object from the pitches returned by applying ring 
 modulation procedures (difference and sum tones of partials).

ARGUMENTS

 - A note-name symbol that is the central pitch from which we perform the
   ring-modulation.  See :partials below.
 - A symbol that is to be the ID for the new set-palette object.

OPTIONAL ARGUMENTS

 keyword arguments
 - :partials. A list of integers that are the partials which the method uses
   to ring modulate. We create partials ascending from the reference-note
   but also ascending from a fundamental calculated so that reference-note
   would be the highest partial in the partials list.  E.g. if
   reference-note were 'a4 (440Hz) and :partials was '(1 2) we'd have
   partial frequencies of 440 and 880, as these are the ascending partials 1
   and 2 from 440, but also have 220, as that is the fundamental for which
   440 would be the highest partial out of (1 2).  Default = '(1 3 5 7).
 - :warn-no-bass. T or NIL to indicate whether to issue a warning when
   ring-mod-bass fails to find suitable bass notes for the generated sets. 
   T = warn. Default = T.
 - :do-bass. T or NIL to indicate whether to add notes created by the
   ring-mod-bass function to the resulting set-palette object. T = create and
   add bass notes. Default = T.
 - :remove-octaves. T or NIL to indicate whether to remove the upper
   instances of any octave-equivalent pitches from the resulting set-palette
   object. T = remove. Default = NIL.
 - :min-bass-notes. An integer that is the minimum number of bass notes to
   be generated and added to the resulting set-palette object. Default = 1.
 - :ring-mod-bass-octave. An integer that is the MIDI octave reference
   number (such as the 4 in 'C4), indicating the octave from which the bass
   note(s) are to be taken.
 - :force-chromatic. T or NIL. If T, force all micro-tone slots of pitch
   objects to be NIL so that they won't be filtered out when a set is to be
   used by a chromatic instrument. See sc-set class force-micro-tone for
   more details. If you want truly chromatic sets make sure to be (in-scale
   :chromatic)  
 - :start-id. An integer which represents the ID number for the first
   set. This will be incremented for each subsequent set generated.

RETURN VALUE

 A set-palette object.

EXAMPLE

;; Simple usage with default keyword argument values
(set-palette-from-ring-mod 'a4 'spfrm-test)

=>
SET-PALETTE: 
PALETTE: 
RECURSIVE-ASSOC-LIST: recurse-simple-data: T
                      num-data: 21
                      linked: NIL
                      full-ref: NIL
ASSOC-LIST: warn-not-found T
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 21, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: SPFRM-TEST, tag: NIL, 
data: (
[...]

;;; Use with the :partials argument
(let ((spfrm2 (set-palette-from-ring-mod 'a4 'spfrm-test
                                           :partials '(2 4 6 8))))
  (loop for cs in (data spfrm2) collect (pitch-symbols cs)))

=> ((BQS0 CS5 E5 GQF5 B5 CS6 DQS6 FQS6 GQF6 AF6 BF6 B6 C7)
    (BQF0 B0 A2 A3 E4 A4 CS5 E5 GQF5)
    (BQS0 FQS6 GQF6 AF6 BF6 B6 C7 GQS7 AF7 AQF7 AQS7 BF7 BQF7)
    (B0 A2 A3 E4 A4 CS5 E5 GQF5 A5 B5) (BQS0 DQF7 DQS7 EQF7 EQS7 FQS7 FS7)
    (BQF0 A2 A3 E4 CS5 E5 GQF5 B5 CS6 DQS6)
    (AQS0 BQF0 B0 GQS7 AF7 AQF7 AQS7 BF7 BQF7)
    (B0 A4 E5 CS6 E6 GQF6 B6 CS7 DQS7 FQS7 GQF7) (B0 A5 A6 E7 A7)
    (B0 A3 CS5 CS6 DQS6 FQS6 GQF6 B6 C7 DQF7 DQS7 FS7 AF7) (BQS0 A5 A6 E7 A7)
    (B0 A4 A5 E6 A6 CS7 E7 GQF7 A7) (BQS0 A5 A6 E7)
    (BQS0 CS6 E6 GQF6 B6 CS7 DQS7 FQS7 GQF7 AF7 BF7 B7 C8)
    (BQF0 B0 BQS0 A2 A3 E4 A4 CS5 GQF5 A5 B5 CS6 E6)
    (BQS0 B6 CS7 DQS7 FQS7 GQF7 AF7) (B0 A3 A4 E5 A5 CS6 E6 GQF6)
    (B0 BQS0 FQS7 GQF7 AF7 BF7 B7 C8) (BQS0 CS6 FQS6 C7 DQS7 FQS7 GQS7 BQF7 C8)
    (B0 A5 A6 E7 A7) (BQS0 A5 E6 CS7 E7 GQF7 B7) (BQS0 A6 A7)
    (BQS0 AF6 B6 DQF7 FS7 AF7 AQS7)
    (BQF0 B0 BQS0 A2 A3 CS5 GQF5 CS6 DQS6 FQS6 GQF6 BF6)
    (BQS0 EQF7 FQS7 GQS7 BQF7 C8) (BQS0 A6 CS7 GQF7 A7) (B0 A5 A6)
    (BQS0 CS7 E7 GQF7 B7))

;;; Use with the :do-bass and :remove-octaves arguments
(let ((spfrm3 (set-palette-from-ring-mod 'a4 'spfrm-test
                                         :do-bass nil
                                         :remove-octaves t)))
  (loop for cs in (data spfrm3) collect (pitch-symbols cs)))
=> ((BQS1 GQF3 EF4 A4 DQF5) (DQF6 DQS6 EF6 F6 FQS6 GQF6 EQF7 EQS7)
    (BQS2 GQF3 A4 DQF5 F5 GQS5) (BQS6 C7 CQS7 DQF7 D7 DQS7)
    (BQS3 EF4 GQF4 DQF5 F5 GQS5 BF5 CQS6) (FQS7 FS7 GQF7 G7 GQS7)
    (GQF5 BF5 DQF6 AQF6 C7 DQS7 F7 GQS7) (BQS1 A4 F5 GQS5 DQS6)
    (GQS6 AQS6 BQS6 DQS7 EQF7 F7 BQF7) (BQS1 EF4 F5 GQS5 CQS6 FQS6)
    (EF7 EQS7 FQS7 GQS7 AQF7 AQS7) (F5 BQS5 GQS6 B6 D7 FS7 AF7 AQS7) (A4 GQF7)
    (A4 CS7 GQF7) (A4 CS7) (EF6 G6 BF6 F7 AQF7 BQS7)
    (BQS1 GQF3 DQF5 CQS6 DQS6 F6 AQS6) (CQS7 DQS7 F7 AQF7 BF7 BQS7)
    (E6 A6 GQF7 B7) (A4 E6 B7) (A6 CS7 E7 B7))

SYNOPSIS

(defun set-palette-from-ring-mod (reference-note id 
                                  &key
                                  (warn-no-bass t)
                                  (do-bass t)
                                  ;; the start id for the sets; will be
                                  ;; incremented  
                                  (start-id 1)
                                  remove-octaves
                                  force-chromatic
                                  (min-bass-notes 1)
                                  (ring-mod-bass-octave 0)
                                  (partials '(1 3 5 7)))

set-palette/set-palette-from-spectra [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DATE

 August 24th 2018

DESCRIPTION

 Create a set-palette by analysing a sound file at regular intervals and
 using the detected frequency components as pitches in a set.

 NB CLM is needed for this method.

ARGUMENTS

 - the sndfile to analyse

OPTIONAL ARGUMENTS

 keyword arguments
 - :id. The ID for the set-palette object to return. If NIL a suitable symbol
   will be created from the sndfile path. Default = NIL.
 - :start. The time in seconds to start the analysis. Default = 0
 - :stop. The time in seconds to stop the analysis. If nil then analysis will
   continue until one millisecond before the end of the sound file. Default =
   NIL.
 - :interval. The time increment in seconds for the analysis start
   point. Default = 0.1
 - :min-pitches. The minimum number of pitches a set may contain. Analyses
   returning less than this number of frequencies will be skipped. Default
   = 5.
 - :pitch-min. The lowest pitch of any set. Pitch object or symbol. Default
   = c1. 
 - :pitch-max. The highest pitch of any set. Pitch object or symbol. Default
   = g7.
 - :round. Round the generated pitches to the nearest in the current scale?
   Default = NIL.
 - :reject-fun. A function that takes a set as an argument and returns T if
   it should be rejected, or NIL if not. Default = NIL.
 - :warn-dups. T or NIL to warn if duplicate pitches are found when calling
   make-complete-set. Default = T. 
 - :gs-keys. Any other keyword arguments to be passed to the get-spectrum
   call (get-spectrum.lsp). In particular :fftsize will be useful here as
   larger windows will result in lower pitches being detected. In any case
   it's worth experimenting with :fftsize. Default: various but :fftsize of
   1024 

RETURN VALUE

 a set-palette object. Each set in the palette has a numerically ascending
 integer ID, starting from 1.

EXAMPLE

(let ((sp (set-palette-from-spectra 
           (concatenate 'string cl-user::+slippery-chicken-home-dir+ 
                        "test-suite/test-sndfiles-dir-1/test-sndfile-3.aiff"))))
  (print-simple sp))
=>
1: DQS2 E5 DQS6 AQF6 AQS6 B6 CQS7 DQF7 
2: E5 GQS5 AQS5 B5 CQS6 AQS6 
4: EQF3 FQS4 E5 AQS5 CS6 AQS6 
5: EQS2 AF3 EQF4 A4 DQF5 E5 AQF5 BQF5 AQS6 
6: B4 EQF5 BF5 CQS6 DQS6 EQS6 GQS6 AQS6 
7: F4 A4 CQS5 EQF5 GQS5 BQS5 CS6 AQS6 
23: E5 BF6 D7 EQF7 E7 FQS7 
NIL

SYNOPSIS

#+clm 
(defun set-palette-from-spectra (sndfile
                                 &key
                                   id
                                   (start 0)
                                   stop
                                   (interval 0.1)
                                   (min-pitches 5)
                                   (pitch-min 'c1)
                                   (pitch-max 'g7)
                                   (round t)
                                   reject-fun
                                   (warn-dups t)
                                   (gs-keys
                                    `(:fftsize 1024 
                                               :order-by clm::freq
                                               :freq-min 20
                                               :freq-max ,(note-to-freq 'b8))))

set-palette/set-palette-p [ Functions ]

[ Top ] [ set-palette ] [ Functions ]

DESCRIPTION

 Test whether a given object is a set-palette object.

ARGUMENTS

 - A lisp object

EXAMPLE

(let ((msp (make-set-palette 
            'test
            '((1 ((1
                   ((bf1 ef2 aqf2 c3 e3 gqf3 gqs3 cs4 d4 g4 a4 cqs5 dqf5 gs5 
                         b5)))
                  (2
                   ((bf1 d2 fqf2 fqs2 b2 c3 f3 g3 bqf3 bqs3 fs4 gs4 a4 cs5 gqf5)
                    :subsets
                    ((tc1 (d2 g3 cs5))
                     (tc2 (eqs2 f3 bqf3))
                     (tc3 (b2 bqs3 gqf5)))))))
              (2 ((1 ((1 1) :transposition 5))
                  (2 ((1 2) :transposition 5))))
              (3 ((1 ((1 1) :transposition -2))
                  (2 ((1 2) :transposition -2))))))))
  (set-palette-p msp))

=> T

RETURN VALUE

 t or nil

SYNOPSIS

(defun set-palette-p (thing)

set-palette/stack [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 30th June 2019, Corfu 

DESCRIPTION

 Call the stack method for each set in the palette. See the method
 description in the sc-set class for details of arguments etc. 

RETURN VALUE

 - the set-palette with new stacked sets (clone before calling if necessary)

SYNOPSIS

(defmethod stack ((sp set-palette) num-stacks &key id by-freq (up t) (down t))

set-palette/thin [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DESCRIPTION

 Apply the thin method to each set in the palette. See the sc-set class
 method for details, including keyword arguments.

SYNOPSIS

(defmethod thin ((sp set-palette) &rest keywords &key &allow-other-keys)

set-palette/wrap [ Methods ]

[ Top ] [ set-palette ] [ Methods ]

DATE

 March 5th 2016, Edinburgh

DESCRIPTION

 Applies the wrap method from the chord class to each set in the
 palette. See the chord class method for details.

RETURN VALUE

 The set-palette object, wrapped.

SYNOPSIS

(defmethod wrap ((sp set-palette) &optional (num-times 1) (transpose t))