Gamut
tuning() only offers a subset of the flexibility offered by gamut(...) which allows complete reconstruction of the notation and tuning system!
The gamut function is modal, in that the instructions within it are specialised and executed in order as follows...
new(): resets the gamut and starts again from scratch, otherwise settings from the current gamut (as either edited or created by tuning()) are preserved.
tuning(...): can also be used within gamut().
pitch_classes=N: sets the number of pitch classes per octave (or pseudo-octave) to N. This clears the "pitches", "note_names", "notes", and "accidentals" tables.
note_names(c d e f ... LIST OF NOTES): sets the list of allowable note names to be used in notes mode (not including accidentals or articulation). These can be multi-character. They are case sensitive, and can also contain numbers and other legal characters, except ' - ,. Even r is allowed. Certain note names (such as r or numbers) already have music functions, however any note name can be prefixed when used by ' to avoid conflicts. (Any bare token encountered in notes mode is assumed to be a note name if prefixed so.) Setting note_names clears the "notes" and "accidentals" tables.
notes(0 2 4 5 7 ... LIST OF INDICES): maps note names to an index within the set of pitch classes, starting from zero. This must be the same length as note_names(). Fractional indices are allowed, but indices must be within the range 0 to pitch_classes. Fractional note values are interpolated between the nearest two pitches, linearly on pitch scale.
accidentals(ACC1(OFFSET) ACC2(LIST OF OFFSETS) ...): creates a rule for accidentals.
ACC1 ACC2 etc. must be unique and not cause confusion with note names as they are directly opposed. No accidentals are created by default.
If a single offset is ascribed to an accidental (positive or negative) than this acts as an offset to the index into the pitch class table for all notes. In 12-tone equal temperament, a typical basic requirement is to set sharps to +1 and flats to -1. E.g. accidentals(es(-1) is(1)).
If a list of offsets is given, this must be one per note name. Offsets may be fractional, e.g. for half-sharps. Any legal character can be used in accidental names except ' - ,.
standard_accidentals(A): creates the "standard set" of accidentals, where A is the number of pitch classes corresponding to a full sharp of flat (which does not have to be an integer). A is often equal to 1.
notes_meantone(tone=M half=H): assigns offsets and number of pitch classes automatically assuming M and H represent the number of steps in tones and half-tones, and an octave is made up only of these intervals. Also, assigns the standard set of accidentals, assuming a sharp or flat is equivalent to the difference in size of M and T. For standard tuning as on a piano, M=2 and H=1.
notes_twotone(major=M minor=Q half=H): is similar, but allows for the exotic effect of major and minor tones to have different numbers of steps. Harmony becomes very complicated under these circumstances!
repeat_ratio=F: sets the size of the octave or pseudo-octave to a value F (of type FREQ_RATIO). F=2 is typical.
equal_tempered(): requests BoxyLady calculate pitch classes automatically as even-tempered. repeat_ratio must be set first.
generator(note(NOTE) r=R g=G n=N step=S): requests BoxyLady calculate pitch classes automatically using a generator. Multiple calls to generator() are possible. Starting with a pitch ratio of R at note NOTE (not centered upon note NOTE; rounded down in case of fractions), BoxyLady makes N steps through the pitch classes of size S (positive or negative), at each step multiplying R by G and inserting this new ratio into the pitch classes table. Wrapping is done automatically when steps go out of bounds, thus repeat_ratio must be set prior to generator(). R and G have FREQ_RATIO format. If pitch_classes and S are coprime, one call to generator of size pitch_classes will fill the whole table. The starting value of R can be arbitrarily set to 1 unless multiple generators at different start notes are needed.
pitches(LIST OF FREQ_RATIO): manually sets the pitch table. The number of parameters must equal pitch_classes. Typically, the first entry is set to 1, although all that matters is that the pitch ratios are relatively correct.
pitch(note(NOTE) r(FREQ_RATIO)): sets a single pitch in the pitch table, identified by note name.
move_pitch(note(NOTE) r(FREQ_RATIO)): as above, but moves relative to previous value.
rotate_pitches(note(NOTE)): rotates the set of pitches such that the current first pitch class is now assigned to NOTE. This can be used to change the home key for regular temperaments.
standard(note(NOTE) r=R): sets the base pitch to which all others are related. For those tuning systems generated automatically, e.g. at program start-up, this defaults to the note a'''' corresponding to a frequency ratio of R=1. However, not all tuning systems generated by the user need have an "a" at all! Whichever note is set will correspond to a sound sample played at its natural sample rate, assuming no transposition is imposed.
list(type=T tol=TOL limit=LIMIT factors Monzo): shows the pitch table. T can be "diatonic", "chromatic", "auto", or omitted which will display either the standard notes C-B, all 12-tone pitches, the current list of note names without accidentals, or all pitch classes. LIMIT if specified as an integer sets the limit assumed for tuning to identify fractional formats of pitch ratios, e.g. 5-limit. TOL is the tolerance, in cents, for identifying fractional formats of pitch ratios, if specified. If factors is specified, prime-factorised intervals are shown. If Monzo is specified, the Monzo for these factors is shown.
The following is a simple example to generate 12-tone equal temperament (which is built in anyway in fact).
key_signature(LIST OF ACCIDENTALS): notes are automatically provided with the accidentals provided by default. The list of accidentals must be the same as the number of note names. Values are in steps through the list of pitch classes.
gamut(
new()
pitch_classes=12
note_names(c d e f g a b)
notes(0 2 4 5 7 9 11)
standard_accidentals(1)
repeat_ratio=2
equal_tempered()
standard(note(a'''') r=1)
)
A simpler example still might only change the repeat ratio once 12-tet is already set up (as at program start-up).
gamut(
repeat_ratio=2.05
equal_tempered()
standard(note=a'''' r=1)
)
There are a lot of potential uses for gamut().
- Defining custom note names such as "ding", "ut", or "h".
- Other European note naming systems, such as German.
- Custom accidentals such as "#" as a name, or odd intervals.
- Non-octave repeating scales.
- Custom tuning systems or microtonal scales.
- World music: Non-Western or non-standard notation systems that do not use the a, b, c notation.