[Function]
(rm-spectrum spectrum1 spectrum2 {keyword value}*)

Ring modulates spectrum1 with spectrum2 and returns the list of pairwise sum and difference tones. Spectral components in the input lists can be Hertz values, key numbers or note names but both lists must contain identical types. For convenience sake, a spectrum consisting of one frequency can be specified as a single value.

rm-spectrum supports the following keyword arguments:

:spectrum {:note | :keynum | :hertz}
Determines the frequency format (hertz values, key numbers or note names) of the components returned in the output spectrum. If the argument is not specified then the output components will be the same type as the input components.
:hz boolean
Specify true if input components are numerical Hertz values otherwise numbers are assumed to be key numbers. The default value is false.
:minimum freq
If specified, then components in the output spectrum that are lower than freq will be octave-shifted upwards until they are equal to or greater than this value. Freq should be the same frequency format as the input components.
:maximum freq
If specified, then components in the output spectrum that are higher than freq will be octave-shifted downwards until they are equal to or less than this value. Freq should be the same frequency format as the input components.
:scale-order {:up | :down | :random}
Determines the ordering of the components in the output spectrum: :up for low-to-high, :down for high-to-low and :random for random (shuffled) order. The default value is :up.
:remove-duplicates boolean
If true then the output spectrum will not contain any duplicate components. The default value is false.

Examples:

Example 1. Ring modulated spectra.

(rm-spectrum 'd5 'e5)
 (d2 ef6)

(rm-spectrum 'a4 '(c4 ds5) :spectrum ':keynum)
 (53.36887 53.741356 77.07837 84.25864)

(rm-spectrum '(300 400) 550 :hz #t)
 (150 250 850 950)

(rm-spectrum '(300 400) 550 :hz #t :spectrum ':note)
 (d3 b3 af5 bf5)

(rm-spectrum '(c4 e4) '(c4 e4 g4) :scale-order ':down)
 (fs5 e5 d5 d5 c3 cs2 cs2 b1)

(rm-spectrum '(c4 e4) '(c4 e4 g4) :remove-duplicates #t)
 (b1 cs2 c3 d5 e5 fs5)

Example 2. Ring modulating random scale selections.

(define (random-rm num select)
  (let ((sel (new heap :of select
                  :for (new random :of '(1 2 3)))))
    (process repeat num
             for set1 = (next sel #t)
             for set2 = (next sel #t)
             for set3 = (rm-spectrum set1 set2 :spectrum ':note
                                     :remove-duplicates #t)
             ;; play set1 as chord
             each k in set1 
             output (new midi :time (now) :keynum k)
             ;; play set2 as chord .5 secs later
             each k in set2
             output (new midi :time (+ (now) .5) :keynum k)
             ;; strum ring modulated set 1 sec later
             each k in set3 as x from 0 by .1
             output (new midi :time (+ (now) 1 x) :keynum k)
             wait 3)))

(events (random-rm 15 (loop for i from 60 to 72 collect i))
        "test.mid")
 "test.mid"

(events (random-rm 15 '(60 62 63 65 67 68 70 72))
        "test.mid")                   
 "test.mid"

See also: