PCH->CPS is useful to convert from pitch class to cycles per second. The syntax is

(pch->cps pitch-class &optional (tuning *default-tuning*))

PCH->CPS is compatible with Csound's cpspch opcode if TUNING is NIL (same uninterpolated table lookup) or a TUNING struct that represents a 12-tone equally-tempered scale. If TUNING is a TUNING struct, PITCH-CLASS is a floating point number xx.yy[z]* where

  xx  = octave number from 0 to 14
  yy  = scale degree from 0 to 99
  z*  = fractional part 0.z* to interpolate between yy and (+ yy 1)

For example:

SCRATCH> (pch->cps 8.0)
261.6255586823373d0

SCRATCH> (mapcar #'pch->cps '(8.0 8.03 8.07 8.10))
(261.6255586823373d0 311.12649215095877d0 391.9947633490325d0
 466.1648230673975d0)

SCRATCH> (mapcar #'pch->cps '(8.09 8.092 8.094 8.096 8.098 8.10))
(440.0003992273812d0 445.2327730918074d0 450.46514695623375d0
 455.69752082066003d0 460.9298946850863d0 466.1648230673975d0)

SCRATCH> (mapcar (lambda (pch) (pch->cps pch nil)) '(8.0 8.03 8.07 8.10))
(261.62555 311.10065 391.9733 466.13742)

(defvar *carlos-beta-tuning*
  (make-tuning
    :notes '(63.8 127.6 191.4 255.2 319.0 382.8 446.6 510.4 574.2 638.0 701.8
             765.6 829.4 893.2 957.0 1020.8 1084.6 1148.4 1212.2 1276.0 1339.8
             1403.6)
    :description "Wendy Carlos' Beta scale with perfect fifth divided by eleven"
    :keynum-base 69
    :freq-base 440
    :degree-index 9))

SCRATCH> (mapcar (lambda (pch) (pch->cps pch *carlos-beta-tuning*))
                 '(8.0 8.04 8.09 8.13 8.18 8.21 8.22 9.0))
(315.7983193277311d0 365.9559432890444d0 440.00025203674517d0
 509.8846239254526d0 613.0501601741471d0 684.7150905041098d0
 710.4196610187067d0 710.4189488799282d0)

We can quantize a list of frequencies with respect to a TUNING structure. The QUANTIZE method also works with real numbers, SIMPLE-VECTOR, SIMPLE-ARRAY and BUFFER-BASE in sorted order. If the object to quantize is a vector or a BUFFER-BASE structure, the keywords START and END are the bounding index designators, and the keyword FILTER-FUNCTION is usable to apply a function to the quantized value. The arguments of that function are the vector index and the quantized value.

(defvar *phr1*
  (make-buffer 15
    :initial-contents (loop repeat 3
                            with l = (mapcar #'pch->cps
                                             '(8.0 8.03 8.07 8.11 8.14))
                            append l)))

SCRATCH> (buffer->list *phr1*)
(261.6255586823373d0 311.12649215095877d0 391.9947633490325d0
 493.8823191422988d0 587.3307285056402d0 261.6255586823373d0
 311.12649215095877d0 391.9947633490325d0 493.8823191422988d0
 587.3307285056402d0 261.6255586823373d0 311.12649215095877d0
 391.9947633490325d0 493.8823191422988d0 587.3307285056402d0)

SCRATCH> (quantize *phr1* *carlos-beta-tuning* :start 4
           :filter-function (lambda (i x) (if (> i 7) (* x 2) x)))

SCRATCH> (buffer->list *phr1*)
(261.6255586823373d0 311.12649215095877d0 391.9947633490325d0
 493.8823191422988d0 590.8683747069908d0 262.6552120696787d0
 315.7983193277311d0 393.94752650215275d0 982.8719402122168d0
 1181.7367494139817d0 525.3104241393575d0 631.5966386554622d0
 787.8950530043055d0 982.8719402122168d0 1181.7367494139817d0)

CPS->PCH converts from Hz to pitch class value:

SCRATCH> (loop for i from 100 to 1000 by 100
               collect (list (cps->pch i)
                             (cps->pch i *carlos-beta-tuning*)))
((6.0734344 5.1279316) (7.0734344 7.0960054) (8.023628 7.2060294)
 (8.073434 8.064093) (8.1120825 8.124642) (9.023628 8.174117)
 (9.050372 8.215946) (9.073434 9.032193) (9.0938225 9.064141)
 (9.1120825 9.092739))

PCH->KEYNUM and KEYNUM->PCH convert from pitch class to keynum and vice versa. The syntax is

(pch->keynum pitch-class &optional (tuning *default-tuning*))
(keynum->pch keynum &optional (tuning *default-tuning*))

Example:

;; The second returned value is the fractional part.
SCRATCH> (pch->keynum 8.00)
60
0.0

Note: if the returned keynum is used without the fractional part, it is necessary to avoid round off problems by adding 1e-6 to the pitch class value before the conversion.

SCRATCH> (pch->keynum 8.03)
62
0.9999733

SCRATCH> (butlast (mapcar #'pch->keynum
                          (loop for oct from 3 to 14
                                append (loop for i to .11 by .01
                                             collect (+ oct i 1e-6))))
                  16)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
 ... 124 125 126 127)

SCRATCH> (subseq (mapcar (lambda (x) (pch->keynum x *carlos-beta-tuning*))
                         (loop for oct from 4 to 11
                               unless (= oct 6) ; jump from 5.21 to 7.00
                                 append (loop for i to .211 by .01
                                              collect (+ oct i 1e-6))))
                 6 134)
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
 ... 124 125 126 127)

SCRATCH> (loop for k below 128 collect (keynum->pch k))
(3.0 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.1 3.11
 4.0 4.01 4.02 4.03 4.04 4.05 4.06 4.07 4.08 4.09 4.1 4.11
 ...
 13.0 13.01 13.02 13.03 13.04 13.05 13.06 13.07)

SCRATCH> (loop for k below 128
               collect (keynum->pch k *carlos-beta-tuning*))
(4.06 4.07 4.08 4.09 4.1 4.11 4.12 4.13 4.14 4.15 4.16 4.17
 4.18 4.19 4.2 4.21 5.0 5.01 5.02 5.03 5.04 5.05 5.06 5.07
 5.08 5.09 5.1 5.11 5.12 5.13 5.14 5.15 5.16 5.17 5.18 5.19
 5.2 5.21 7.0 7.01 7.02 7.03 7.04 7.05 7.06 7.07 7.08 7.09
 7.1 7.11 7.12 7.13 7.14 7.15 7.16 7.17 7.18 7.19 7.2 7.21
 8.0 8.01 8.02 8.03 8.04 8.05 8.06 8.07 8.08 8.09 8.1 8.11
 ....
 10.19 10.2 10.21 11.0 11.01)

Sourceforge project page