signal/tuning
one degree of a scale: a frequency ratio or a size in cents.
Scale
(Scale)
a list of pitches above 1/1, the last of them the period.
Keymap
(Keymap)
which notes play which scale degrees, and the reference pitch.
Tuning
(Tuning)
a scale under a keymap, flattened into one repeating pattern.
scale-new
(scale-new [description : cstr pitches : (Vec Pitch)] :)
a scale from a description and its pitches.
| description | one line of text, kept for `scale->scl` | |
| pitches | the degrees, at least one; ratios must be positive and | |
| cents finite |
(Ok scale), or (Err message) naming the first bad pitch.
;; 5-limit just major
(scale-new "Just major" [(Ratio 9 8) (Ratio 5 4) (Ratio 4 3) (Ratio 3 2)
(Ratio 5 3) (Ratio 15 8) (Ratio 2 1)])
Since: signal v0.1.0
scale-edo
(scale-edo [n :int] :)
`n` equal divisions of the octave.
| n | steps per octave, clamped to [1, 1048576] |
The scale.
(scale-cents (scale-edo 19) 1) ; => 63.1579
Since: signal v0.1.0
scale-size
(scale-size [s : Scale] :)
the number of pitches in a scale, the period included.
| s | the scale |
The note count of its `.scl` file; 12 for `(scale-edo 12)`.
(scale-size (scale-edo 31)) ; => 31
Since: signal v0.1.0
scale-description
(scale-description [s : Scale] :)
the scale's one-line description.
| s | the scale |
The description, owned by the scale (valid for the process).
(scale-description (scale-edo 19)) ; => "19 equal divisions of the octave"
Since: signal v0.1.0
scale-pitch
(scale-pitch [s : Scale k :int] :)
degree `k` of a scale, as it was given.
| s | the scale | |
| k | the degree: 0 is the implicit 1/1, `(scale-size s)` the period |
(some pitch) for 0 <= k <= size -- degree 0 is `(Ratio 1 1)` -- and (none) outside that range.
(scale-pitch (scale-edo 12) 12) ; => (some (Ratio 2 1))
Since: signal v0.1.0
scale-cents
(scale-cents [s : Scale k :int] :)
the size of degree `k` in cents, for any integer `k`.
| s | the scale | |
| k | any degree |
Cents above the 1/1.
(scale-cents (scale-edo 12) 7) ; => 700 (scale-cents (scale-edo 12) 14) ; => 1400 (scale-cents (scale-edo 12) -1) ; => -100
Since: signal v0.1.0
scale-period
(scale-period [s : Scale] :)
the interval the scale repeats at, in cents.
| s | the scale |
The size of its last degree; 1200 for an octave-repeating scale.
(scale-period (scale-edo 19)) ; => 1200
Since: signal v0.1.0
scl-parse
(scl-parse [text : cstr] :)
read a scale from the text of a Scala `.scl` file.
| text | the file's contents |
(Ok scale), or (Err message) naming the line at fault.
(scl-parse "! pelog.scl\nA pentatonic\n 5\n 120.\n 270.\n 540.\n 670.\n 2/1\n")
Since: signal v0.1.0
scl-load
(scl-load [path : cstr])
read a scale from a Scala `.scl` file.
| path | the file |
(Ok scale), or (Err message) if the file cannot be read or parsed.
(scl-load "scales/marvel12.scl")
Since: signal v0.1.0
scale->scl
(scale->scl [s : Scale] :)
the text of a Scala `.scl` file for a scale.
| s | the scale |
The file's contents.
(println (string/to-cstr (scale->scl (scale-edo 5)))) ;; ! Written by tur-signal ;; ! ;; 5 equal divisions of the octave ;; 5 ;; ! ;; 240.0 ;; 480.0 ;; 720.0 ;; 960.0 ;; 2/1
Since: signal v0.1.0
keymap-linear
(keymap-linear [middle :int ref-key :int ref-freq :float] :)
every key plays the next scale degree.
| middle | the note that plays degree 0 | |
| ref-key | the note whose frequency is fixed | |
| ref-freq | its frequency in Hz, > 0 |
The keymap.
(keymap-linear 60 69 440.0)
Since: signal v0.1.0
keymap-new
(keymap-new [middle :int ref-key :int ref-freq :float octave-degree :int entries : (Vec MapEntry)] :)
a keymap that repeats a pattern of entries.
| middle | the note that plays the first entry | |
| ref-key | the note whose frequency is fixed; must be mapped | |
| ref-freq | its frequency in Hz, > 0 | |
| octave-degree | the degree each repetition rises by, >= 0 | |
| entries | the pattern; degrees must be >= 0 |
(Ok keymap), or (Err message).
;; two keys: the 1/1 and the fifth (degree 7 of 12), repeating by octaves (keymap-new 60 60 261.6256 12 [(Degree 0) (Degree 7)])
Since: signal v0.1.0
keymap-size
(keymap-size [k : Keymap] :)
the length of the pattern; 0 for a linear map.
| k | the keymap |
The number of entries.
(keymap-size (keymap-linear 60 69 440.0)) ; => 0
Since: signal v0.1.0
keymap-first
(keymap-first [k : Keymap] :)
the first note the `.kbm` file retunes.
| k | the keymap |
The note number; 0 unless a `.kbm` said otherwise.
(keymap-first (keymap-linear 60 69 440.0)) ; => 0
Since: signal v0.1.0
keymap-last
(keymap-last [k : Keymap] :)
the last note the `.kbm` file retunes.
| k | the keymap |
The note number; 127 unless a `.kbm` said otherwise.
(keymap-last (keymap-linear 60 69 440.0)) ; => 127
Since: signal v0.1.0
keymap-middle
(keymap-middle [k : Keymap] :)
the note that plays the pattern's first entry.
| k | the keymap |
The note number.
(keymap-middle (keymap-linear 60 69 440.0)) ; => 60
Since: signal v0.1.0
keymap-reference
(keymap-reference [k : Keymap] :)
the note whose frequency is fixed.
| k | the keymap |
The note number.
(keymap-reference (keymap-linear 60 69 440.0)) ; => 69
Since: signal v0.1.0
keymap-frequency
(keymap-frequency [k : Keymap] :)
the reference note's frequency.
| k | the keymap |
Hz.
(keymap-frequency (keymap-linear 60 69 440.0)) ; => 440
Since: signal v0.1.0
keymap-octave-degree
(keymap-octave-degree [k : Keymap] :)
the scale degree each repetition rises by.
| k | the keymap |
The formal octave; 0 means the scale's period.
(keymap-octave-degree (keymap-linear 60 69 440.0)) ; => 0
Since: signal v0.1.0
keymap-entries
(keymap-entries [k : Keymap] :)
the pattern, as `keymap-new` takes it.
| k | the keymap |
A new Vec of `(keymap-size k)` entries; empty for a linear map.
(vec-len (keymap-entries (keymap-linear 60 69 440.0))) ; => 0
Since: signal v0.1.0
kbm-parse
(kbm-parse [text : cstr] :)
read a keymap from the text of a Scala `.kbm` file.
| text | the file's contents |
(Ok keymap), or (Err message) naming the line at fault.
;; linear, A4 = 432 Hz (kbm-parse "0\n0\n127\n60\n69\n432.0\n0\n")
Since: signal v0.1.0
kbm-load
(kbm-load [path : cstr])
read a keymap from a Scala `.kbm` file.
| path | the file |
(Ok keymap), or (Err message) if the file cannot be read or parsed.
(kbm-load "maps/whitekeys.kbm")
Since: signal v0.1.0
keymap->kbm
(keymap->kbm [k : Keymap] :)
the text of a Scala `.kbm` file for a keymap.
| k | the keymap |
The file's contents.
(println (string/to-cstr (keymap->kbm (keymap-linear 60 69 440.0))))
Since: signal v0.1.0
tuning-new
(tuning-new [s : Scale k : Keymap] :)
a scale played through a keymap.
| s | the scale | |
| k | the keymap |
The tuning, for `mtof-tuned` and `ftom-tuned`.
;; standard tuning: mtof-tuned of it is mtof (tuning-new (scale-edo 12) (keymap-linear 60 69 440.0))
Since: signal v0.1.0
tuning-scale
(tuning-scale [t : Tuning] :)
the scale a tuning plays.
| t | the tuning |
Its scale.
(scale-size (tuning-scale t))
Since: signal v0.1.0
tuning-keymap
(tuning-keymap [t : Tuning] :)
the keymap a tuning plays through.
| t | the tuning |
Its keymap.
(keymap-frequency (tuning-keymap t)) ; => the reference frequency
Since: signal v0.1.0
tuning-mapped?
(tuning-mapped? [t : Tuning key :int] :)
whether a note plays a scale degree of its own.
| t | the tuning | |
| key | a note number |
True if the keymap maps it; always true for a linear keymap.
(tuning-mapped? white-keys 61) ; => false (C#4)
Since: signal v0.1.0
mtof-tuned
(mtof-tuned [t : Tuning m :float] :)
note number to frequency in Hz, in a tuning.
| t | the tuning | |
| m | note number; any float |
The frequency in Hz; NaN for a NaN note.
(mtof-tuned (tuning-new (scale-edo 19) (keymap-linear 60 69 440.0)) 70.0) ; => 456.348 (one nineteenth of an octave above A4)
Since: signal v0.1.0
ftom-tuned
(ftom-tuned [t : Tuning f :float] :)
frequency in Hz to note number, in a tuning.
| t | the tuning | |
| f | frequency in Hz, > 0 |
The note number.
(ftom-tuned (tuning-new (scale-edo 19) (keymap-linear 60 69 440.0)) 456.348) ; => 70
Since: signal v0.1.0
Internal definitions
__tuning_msg-- a fresh heap copy of `fmt` with one integer formatted in.__scale_alloc-- a scale of `n` (clamped to [1, 1048576]) zero-cent__scale_free-- release a scale `scale-new` rejected.__scale_set_cents!-- make degree `k` (1-based) of `s` `c` cents.__scale_set_ratio!-- make degree `k` (1-based) of `s` the ratio num/den.__finite?-- true unless `x` is NaN or infinite.__scale_ratio?-- whether degree `k` (1-based) was given as a ratio.__scale_num-- numerator of ratio degree `k` (1-based).__scale_den-- denominator of ratio degree `k` (1-based).__scale_fill-- store `pitches` into `s`; 0, or the 1-based index of the__scale_edo-- n equal divisions of 2/1 (see scale-edo).__scale_degree_cents-- cents of degree `k` (1-based, in range).__scl_parse-- the .scl parser; the error is a heap cstr.__tuning_slurp-- a file's contents as a heap cstr, or an error message.__tuning_free-- free a heap cstr from __tuning_slurp.__tuning_fmt_num-- the shortest decimal that reads back as `v`, always__scl_header-- the .scl text up to the first pitch, as a heap cstr.__scl_ratio-- "n/d" for ratio degree `k` (1-based), as a heap cstr.__scl_line!-- append " <value>\n" to the builder, taking `v` (heap).__keymap_alloc-- a keymap with `size` unmapped entries.__keymap_map!-- make entry `i` of `k` play degree `d` (>= 0).__keymap_raw-- entry `i` of `k`: the degree, or -1 if unmapped.__keymap_fill-- store `entries` into `k`; 0, or the 1-based index of the__keymap_ref_mapped?-- whether the reference note plays a degree.__kbm_parse-- the .kbm parser; the error is a heap cstr.__kbm_format-- the .kbm text of a keymap, given its frequency as text,__tuning_build-- flatten a scale under a keymap into one pattern.__tuning_scale-- the scale pointer of a tuning.__tuning_keymap-- the keymap pointer of a tuning.