pub struct Scl { /* private fields */ }
Expand description
Scale format according to http://www.huygens-fokker.org/scala/scl_format.html.
The Scl
format describes a periodic scale in relative pitches. You can access those pitches using Scl::relative_pitch_of
.
To retrieve absolute Pitch
information, you need to pair the Scl
struct with a Kbm
or KbmRoot
struct (see implementations of the Tuning
or KeyboardMapping
trait for more info).
Examples
use tune::tuning::Tuning;
let scl = scala::create_harmonics_scale(None, SegmentType::Otonal, 8, 8, None).unwrap();
let kbm = KbmRoot::from(Note::from_midi_number(43).at_pitch(Pitch::from_hz(100.0)));
let tuning = (scl, kbm);
assert_approx_eq!(tuning.pitch_of(PianoKey::from_midi_number(43)).as_hz(), 100.0);
assert_approx_eq!(tuning.pitch_of(PianoKey::from_midi_number(44)).as_hz(), 112.5);
assert_approx_eq!(tuning.pitch_of(PianoKey::from_midi_number(45)).as_hz(), 125.0);
Implementations§
source§impl Scl
impl Scl
pub fn builder() -> SclBuilder
pub fn set_description(&mut self, description: impl Into<String>)
pub fn description(&self) -> &str
pub fn period(&self) -> Ratio
pub fn num_items(&self) -> u16
sourcepub fn relative_pitch_of(&self, degree: i32) -> Ratio
pub fn relative_pitch_of(&self, degree: i32) -> Ratio
Retrieves relative pitches without requiring any Kbm
reference.
Examples
let scl = Scl::builder()
.push_cents(100.0)
.push_cents(50.0)
.push_cents(175.0)
.push_cents(150.0)
.build().unwrap();
assert_approx_eq!(scl.period().as_cents(), 150.0);
assert_approx_eq!(scl.relative_pitch_of(-1).as_cents(), 25.0); // 25.0 = previous period + 175.0
assert_approx_eq!(scl.relative_pitch_of(0).as_cents(), 0.0);
assert_approx_eq!(scl.relative_pitch_of(1).as_cents(), 100.0);
assert_approx_eq!(scl.relative_pitch_of(2).as_cents(), 50.0);
assert_approx_eq!(scl.relative_pitch_of(3).as_cents(), 175.0);
assert_approx_eq!(scl.relative_pitch_of(4).as_cents(), 150.0);
assert_approx_eq!(scl.relative_pitch_of(5).as_cents(), 250.0); // 250.0 = next period + 100.0
sourcepub fn sorted_relative_pitch_of(&self, degree: i32) -> Ratio
pub fn sorted_relative_pitch_of(&self, degree: i32) -> Ratio
Retrieves relative pitches in ascending order without requiring any Kbm
reference.
Examples
let scl = Scl::builder()
.push_cents(100.0)
.push_cents(50.0)
.push_cents(175.0)
.push_cents(150.0)
.build().unwrap();
assert_approx_eq!(scl.period().as_cents(), 150.0);
assert_approx_eq!(scl.sorted_relative_pitch_of(-1).as_cents(), -50.0); // -50.0 = previous period + 100.0
assert_approx_eq!(scl.sorted_relative_pitch_of(0).as_cents(), 0.0);
assert_approx_eq!(scl.sorted_relative_pitch_of(1).as_cents(), 25.0); // 25.0 = previous period + 175.0
assert_approx_eq!(scl.sorted_relative_pitch_of(2).as_cents(), 50.0);
assert_approx_eq!(scl.sorted_relative_pitch_of(3).as_cents(), 100.0);
assert_approx_eq!(scl.sorted_relative_pitch_of(4).as_cents(), 150.0);
assert_approx_eq!(scl.sorted_relative_pitch_of(5).as_cents(), 175.0);
sourcepub fn find_by_relative_pitch(
&self,
relative_pitch: Ratio
) -> Approximation<i32>
pub fn find_by_relative_pitch( &self, relative_pitch: Ratio ) -> Approximation<i32>
Finds the approximate degree of a relative pitch without requiring any Kbm
reference.
Examples
let scl = Scl::builder()
.push_cents(100.0)
.push_cents(50.0)
.push_cents(175.0)
.push_cents(150.0)
.build().unwrap();
assert_approx_eq!(scl.period().as_cents(), 150.0);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(0.0)).approx_value, 0);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(10.0)).approx_value, 0);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(20.0)).approx_value, -1); // 25.0 = previous period + 175.0
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(30.0)).approx_value, -1); // 25.0 = previous period + 175.0
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(40.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(50.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(60.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(70.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(80.0)).approx_value, 1);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(90.0)).approx_value, 1);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(100.0)).approx_value, 1);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(110.0)).approx_value, 1);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(120.0)).approx_value, 1);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(130.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(140.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(150.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(160.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(170.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(180.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(190.0)).approx_value, 6); // 200.0 = next period + 100.0
assert_eq!(scl.find_by_relative_pitch(Ratio::from_cents(200.0)).approx_value, 6); // 200.0 = next period + 100.0
sourcepub fn find_by_relative_pitch_sorted(
&self,
relative_pitch: Ratio
) -> Approximation<i32>
pub fn find_by_relative_pitch_sorted( &self, relative_pitch: Ratio ) -> Approximation<i32>
Finds the approximate degree of a relative pitch in ascending order without requiring any Kbm
reference.
Examples
let scl = Scl::builder()
.push_cents(100.0)
.push_cents(50.0)
.push_cents(175.0)
.push_cents(150.0)
.build().unwrap();
assert_approx_eq!(scl.period().as_cents(), 150.0);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(0.0)).approx_value, 0);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(10.0)).approx_value, 0);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(20.0)).approx_value, 1); // 25.0 = previous period + 175.0
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(30.0)).approx_value, 1); // 25.0 = previous period + 175.0
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(40.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(50.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(60.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(70.0)).approx_value, 2);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(80.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(90.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(100.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(110.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(120.0)).approx_value, 3);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(130.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(140.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(150.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(160.0)).approx_value, 4);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(170.0)).approx_value, 5);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(180.0)).approx_value, 5);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(190.0)).approx_value, 6);
assert_eq!(scl.find_by_relative_pitch_sorted(Ratio::from_cents(200.0)).approx_value, 6); // 200.0 = next period + 50.0
sourcepub fn import(reader: impl Read) -> Result<Self, SclImportError>
pub fn import(reader: impl Read) -> Result<Self, SclImportError>
Imports the given file in SCL format.
let scl_file = [
"!A comment",
" !An indented comment",
" Example scale ",
"7",
"100.",
"150.0 ignore text after first whitespace",
" ", // ignore blank line
"!175.0 ignore whole line",
"200.0 .ignore additional dots",
" 6/5 ",
"5/4 (ignore parentheses)",
"3/2 /ignore additional slashes",
"2",
];
let scl = Scl::import(scl_file.join("\n").as_bytes()).unwrap();
assert_eq!(scl.description(), "Example scale");
assert_eq!(scl.num_items(), 7);
assert_approx_eq!(scl.relative_pitch_of(0).as_cents(), 0.0);
assert_approx_eq!(scl.relative_pitch_of(1).as_cents(), 100.0);
assert_approx_eq!(scl.relative_pitch_of(2).as_cents(), 150.0);
assert_approx_eq!(scl.relative_pitch_of(3).as_cents(), 200.0);
assert_approx_eq!(scl.relative_pitch_of(4).as_float(), 6.0 / 5.0);
assert_approx_eq!(scl.relative_pitch_of(5).as_float(), 5.0 / 4.0);
assert_approx_eq!(scl.relative_pitch_of(6).as_float(), 3.0 / 2.0);
assert_approx_eq!(scl.relative_pitch_of(7).as_float(), 2.0);
assert_approx_eq!(scl.period().as_float(), 2.0);
sourcepub fn export(&self) -> SclExport<'_>
pub fn export(&self) -> SclExport<'_>
Exports the current scale in SCL file format.
Examples
let scl = Scl::builder()
.push_cents(100.0)
.push_ratio("1:13:3".parse().unwrap())
.push_fraction(4, 3)
.push_int(2)
.build_with_description("Example scale")
.unwrap();
assert_eq!(
format!("{}", scl.export()).lines().collect::<Vec<_>>(),
["Example scale", "4", "100.000", "146.304", "4/3", "2"]
);