I’m very excited to share a pair of flexible bit-mask scale OPs for working with 12TET that I made, called N.B and N.BX. I hope they would bring joy to other teletype users, and ultimately I hope they could be considered for adaption into the official firmware.
teletype.hex (703.3 KB) teletype.pdf (641.8 KB) teletype_op_nbx.diff (13.5 KB)
They’re centered around the idea that users can define their own scale on the fly, while still making it easy to use by including a bunch of preset scales. There’s a multi-scale version as well, called N.BX (basically store up to eight scales and use them at the flick of an index). No lookup-tables (doesn’t take up a lot of memory), works with any number of notes in any combination, non-wrapping 1-indexed degree including negative degrees.
Remixed from the manual (for the actual manual, take a look at the attached teletype.pdf) + some added info:
Converts a degree in a user-defined equal temperament scale to a value usable by the CV outputs.
N.B d
Get degree d
of scale
N.BX i d
Get degree d
of scale at index i
N.B r s
Set scale, r
is root note, s
is scale, either set with bit mask or by selecting a preset (s < 1). Default root is 0, default scale is Major.
N.BX i r s
Set scale at index i
.
Note that N.B is actually addressing scale at index 0 “behind the scenes”, so N.B and N.BX 0 are equivalent.
Examples (note names assumes your oscillator is tuned with 0V=C):
CV 1 N.B 1 ==> set CV 1 to 1st degree of default scale
(C, value corresponding to N 0)
N.B 0 B101011010101 ==> set scale to C-major (default)
CV 1 N.B 1 ==> set CV 1 get 1st degree of scale
(C, value corresponding to N 0)
N.B 2 B101011010101 ==> set scale to D-major
CV 1 N.B 3 ==> set CV 1 to 3rd degree of scale
(F#, value corresponding to N 6)
N.B 3 B100101010010 ==> set scale to Eb-minor pentatonic
CV 1 N.B 2 ==> set CV 1 to 2nd degree of scale
(Gb, value corresponding to N 6)
N.B 5 -3 ==> set scale to F-lydian using preset
N.BX 1 3 B100101010010 ==> set scale at index 1 to Eb-minor pentatonic
CV N.BX 1 2 ==> set CV 1 to 2nd degree of scale
(Gb, value corresponding to N 6)
N.BX 2 5 -3 ==> set scale at index 2 to F-lydian using preset
Values of s
less than 1 sets the bit-mask to a preset scale:
0: Ionian (major)
-1: Dorian
-2: Phrygian
-3: Lydian
-4: Mixolydian
-5: Aeolean (natural minor)
-6: Locrian
-7: Melodic minor
-8: Harmonic minor
-9: Major pentatonic
-10: Minor pentatonic
-11 Whole note (1st Messiaen mode)
-12 Octatonic (half-whole, 2nd Messiaen mode)
-13 Octatonic (whole-half)
-14 3rd Messiaen mode
-15 4th Messiaen mode
-16 5th Messiaen mode
-17 6th Messiaen mode
-18 7th Messiaen mode
-19 Augmented
Questions (ultimately for @scanner_darkly):
- I strongly feel that the user should be able to setup scales with the B binary notation. However it seems that B is “backwards”, which at places shows when using these OPs. I suppose we’re pretty set on the way B works?
- N.B and N.BX are defined almost identical in the source, I’d like to make a single setter core and a single getter core, similar to the chaos OPs, and then call the core in for instance op_N_BX_set and op_N_B_set (the difference would be that op_N_B_set always works on scale at index 0). However I’m not sure where (which file) it would be most appropriate to put the core functions?
- At the moment, there are 8 scales indexable by i. A friend suggested adding more, to be able to chain scales. Since each index takes up just two ints of memory (one for the root and one for the bit mask), I think the number could be higher, any thoughts on this?
- There are a few magic numbers in the code, like the number of indexable scales, I’d like to use #define instead, where should I place such #define?