Struct tune::scala::Kbm

source ·
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

source

pub fn builder(kbm_root: impl Into<KbmRoot>) -> KbmBuilder

source

pub fn kbm_root(&self) -> KbmRoot

source

pub fn set_kbm_root(&mut self, kbm_root: KbmRoot)

source

pub fn range(&self) -> Range<PianoKey>

source

pub fn range_iter( &self ) -> impl DoubleEndedIterator<Item = PianoKey> + ExactSizeIterator<Item = PianoKey> + 'static

source

pub fn formal_octave(&self) -> i16

source

pub fn num_items(&self) -> u16

source

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));
source

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));
source

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§

source§

impl Clone for Kbm

source§

fn clone(&self) -> Kbm

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Kbm

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.