pub struct Kbm { /* private fields */ }
Expand description
Keyboard mappings according to http://www.huygens-fokker.org/scala/help.htm#mappings.
To better understand how keyboard mappings work have a look at the documented methods of this struct.
For more specialized linear keyboard mappings use KbmRoot
.
Implementations§
source§impl Kbm
impl Kbm
pub fn builder(kbm_root: impl Into<KbmRoot>) -> KbmBuilder
pub fn kbm_root(&self) -> KbmRoot
pub fn set_kbm_root(&mut self, kbm_root: KbmRoot)
pub fn range(&self) -> Range<PianoKey>
pub fn range_iter( &self ) -> impl DoubleEndedIterator<Item = PianoKey> + ExactSizeIterator<Item = PianoKey> + 'static
pub fn formal_octave(&self) -> i16
pub fn num_items(&self) -> u16
sourcepub fn scale_degree_of(&self, key: PianoKey) -> Option<i32>
pub fn scale_degree_of(&self, key: PianoKey) -> Option<i32>
Returns the scale degree for the given PianoKey
.
Examples
let kbm = Kbm::builder(Note::from_midi_number(62))
.range(PianoKey::from_midi_number(10)..PianoKey::from_midi_number(100))
// KBM degree 0 maps to SCL degree 0
.push_mapped_key(0)
// KBM degree 1 maps to SCL degree 4
.push_mapped_key(4)
// KBM degree 2 is unmapped
.push_unmapped_key()
// KBM degree 3 maps to SCL degree 4 again (!)
.push_mapped_key(4)
// A KBM degree shift of 4 (num_items) leads to an SCL degree shift of 17 (formal_octave)
.formal_octave(17)
.build()
.unwrap();
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(10)), Some(-221));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(60)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(61)), Some(-13));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(62)), Some(0));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(63)), Some(4));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(64)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(65)), Some(4));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(66)), Some(17));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(67)), Some(21));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(68)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(99)), Some(157));
// Not in the range 10..100
for midi_number in (0..10).chain(100..128) {
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(midi_number)), None);
}
// If the mapping is empty, a linear mapping is assumed.
let empty_kbm = Kbm::builder(Note::from_midi_number(62))
// This has no effect
.formal_octave(42)
.build()
.unwrap();
assert_eq!(empty_kbm.scale_degree_of(PianoKey::from_midi_number(61)), Some(-1));
assert_eq!(empty_kbm.scale_degree_of(PianoKey::from_midi_number(62)), Some(0));
assert_eq!(empty_kbm.scale_degree_of(PianoKey::from_midi_number(63)), Some(1));
sourcepub fn import(reader: impl Read) -> Result<Self, KbmImportError>
pub fn import(reader: impl Read) -> Result<Self, KbmImportError>
Imports the given file in KBM format.
let input = [
"!A comment",
" !An indented comment",
"6 <- Official map size. Can be larger than the number of provided mapping entries!",
"10",
"99 (Rust's Range type is right exclusive. The upper bound becomes 100.)",
"62",
" 69 ",
"432.0 = healing frequency",
"17",
"! Start of the mapping table",
"0",
"4",
"x means unmapped",
"4",
"X - uppercase is supported",
"! End of the mapping table. 'x'es are added to match the official map size.",
];
let kbm = Kbm::import(input.join("\n").as_bytes()).unwrap();
assert_eq!(kbm.kbm_root().ref_key.midi_number(), 69);
assert_approx_eq!(kbm.kbm_root().ref_pitch.as_hz(), 432.0);
assert_eq!(kbm.kbm_root().root_offset, -7);
assert_eq!(kbm.range().start.midi_number(), 10);
assert_eq!(kbm.range().end.midi_number(), 100);
assert_eq!(kbm.formal_octave(), 17);
assert_eq!(kbm.num_items(), 6);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(69)), Some(0));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(70)), Some(4));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(71)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(72)), Some(4));
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(73)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(74)), None);
assert_eq!(kbm.scale_degree_of(PianoKey::from_midi_number(75)), Some(17));
sourcepub fn export(&self) -> KbmExport<'_>
pub fn export(&self) -> KbmExport<'_>
Exports the current keyboard mapping in KBM file format.
Examples
let mut kbm_root = KbmRoot {
ref_key: PianoKey::from_midi_number(69),
ref_pitch: Pitch::from_hz(432.0),
root_offset: -9,
};
// White keys on 22-edo
let kbm = Kbm::builder(kbm_root)
.range(PianoKey::from_midi_number(10)..PianoKey::from_midi_number(100))
.push_mapped_key(0)
.push_unmapped_key()
.push_mapped_key(4)
.push_unmapped_key()
.push_mapped_key(8)
.push_mapped_key(9)
// ... etc.
.formal_octave(22)
.build()
.unwrap();
assert_eq!(
format!("{}", kbm.export()).lines().collect::<Vec<_>>(),
["6", "10", "99", "60", "69", "432.000", "22", "0", "x", "4", "x", "8", "9"]
);
Trait Implementations§
Auto Trait Implementations§
impl RefUnwindSafe for Kbm
impl Send for Kbm
impl Sync for Kbm
impl Unpin for Kbm
impl UnwindSafe for Kbm
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more