Skip to content

Commit

Permalink
Add "crunchy" option.
Browse files Browse the repository at this point in the history
  • Loading branch information
twitchax committed Dec 26, 2022
1 parent c4c162a commit 9c45493
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 4 deletions.
8 changes: 6 additions & 2 deletions src/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ enum Command {
/// Fade in duration (in seconds)
#[arg(short, long, default_value_t = 0.1f32)]
fade_in: f32,

/// Sets whether or not the chord should be played "crunchy"
#[arg(short, long, default_value_t = false)]
crunchy: bool,
},

/// Attempt to guess the chord from a set of notes (ordered by simplicity)
Expand All @@ -72,8 +76,8 @@ fn start(args: Args) -> Void {

describe(&chord);
},
Some(Command::Play { symbol, octave, inversion, delay, length, fade_in }) => {
let chord = Chord::parse(&symbol)?.with_octave(Octave::Zero + octave).with_inversion(inversion);
Some(Command::Play { symbol, octave, inversion, delay, length, fade_in, crunchy }) => {
let chord = Chord::parse(&symbol)?.with_octave(Octave::Zero + octave).with_inversion(inversion).with_crunchy(crunchy);

play(&chord, delay, length, fade_in)?;
},
Expand Down
29 changes: 27 additions & 2 deletions src/chord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashSet, fmt::Display};

use pest::Parser;

use crate::{note::{Note, CZero, NoteRecreator}, modifier::{Modifier, Extension, Degree, HasIsDominant, known_modifier_sets, likely_extension_sets, one_off_modifier_sets}, known_chord::{KnownChord, HasRelativeChord, HasRelativeScale}, interval::Interval, base::{HasDescription, HasName, HasStaticName, Res, Parsable}, parser::{ChordParser, Rule, note_str_to_note}, octave::{Octave, HasOctave}, named_pitch::HasNamedPitch, pitch::{HasFrequency}};
use crate::{note::{Note, CZero, NoteRecreator}, modifier::{Modifier, Extension, Degree, HasIsDominant, known_modifier_sets, likely_extension_sets, one_off_modifier_sets}, known_chord::{KnownChord, HasRelativeChord, HasRelativeScale}, interval::{Interval, CanReduceFrame}, base::{HasDescription, HasName, HasStaticName, Res, Parsable}, parser::{ChordParser, Rule, note_str_to_note}, octave::{Octave, HasOctave}, named_pitch::HasNamedPitch, pitch::{HasFrequency}};

// Traits.

Expand Down Expand Up @@ -74,6 +74,8 @@ pub trait Chordable {
fn with_slash(self, slash: Note) -> Chord;
/// Sets the octave of the implementor (most likely the root note of a chord), and returns a new chord.
fn with_octave(self, octave: Octave) -> Chord;
/// Sets whether or not the implementor (most likely a [`Chord`]) is crunchy.
fn with_crunchy(self, is_crunchy: bool) -> Chord;

// Modifiers.

Expand Down Expand Up @@ -228,6 +230,10 @@ pub struct Chord {
extensions: HashSet<Extension>,
/// The inversion of the chord.
inversion: u8,
/// Whether or not this chord is "crunchy".
///
/// Crunchy chords take extensions down an octave, which gives the chord some "crunch".
is_crunchy: bool,
}

// Impls.
Expand All @@ -240,7 +246,8 @@ impl Chord {
slash: None,
modifiers: HashSet::new(),
extensions: HashSet::new(),
inversion: 0
inversion: 0,
is_crunchy: false,
}
}

Expand Down Expand Up @@ -465,6 +472,13 @@ impl Chordable for Chord {
}
}

fn with_crunchy(self, is_crunchy: bool) -> Chord {
Chord {
is_crunchy,
..self
}
}

// Modifiers.

fn minor(self) -> Chord {
Expand Down Expand Up @@ -839,6 +853,13 @@ impl HasRelativeChord for Chord {
if extensions.contains(&Extension::Add13) {
result.push(Interval::MajorThirteenth);
}

// If this chord is crunchy, bring all "octave" intervals down to the first octave frame.
if self.is_crunchy {
for interval in &mut result {
*interval = interval.reduce_frame();
}
}

result.sort();
result.dedup();
Expand Down Expand Up @@ -1159,6 +1180,10 @@ mod tests {
assert_eq!(Chord::new(C).seven().sharp13().chord(), vec![C, E, G, BFlat, ASharpFive]);
assert_eq!(Chord::new(C).seven().sharp_thirteen().chord(), vec![C, E, G, BFlat, ASharpFive]);

// Crunchy.

assert_eq!(Chord::new(C).seven().sharp9().with_crunchy(true).chord(), vec![C, DSharp, E, G, BFlat]);

// Slashes.

assert_eq!(Chord::new(C).with_slash(D).chord(), vec![DThree, C, E, G]);
Expand Down
63 changes: 63 additions & 0 deletions src/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ pub trait HasEnharmonicDistance {
fn enharmonic_distance(&self) -> i8;
}

/// A trait for types that can be "reduced" to a single "frame" (usually an interval, and usually within an octave).
pub trait CanReduceFrame {
/// Returns the reduced frame of the type.
fn reduce_frame(self) -> Self;
}

// Enum.

/// An enum representing the interval between two notes.
Expand Down Expand Up @@ -187,4 +193,61 @@ impl HasOctave for Interval {
Interval::AugmentedThirteenth => Octave::One,
}
}
}

impl CanReduceFrame for Interval {
fn reduce_frame(self) -> Self {
match self {
Interval::PerfectUnison => Interval::PerfectUnison,
Interval::DiminishedSecond => Interval::DiminishedSecond,

Interval::AugmentedUnison => Interval::AugmentedUnison,
Interval::MinorSecond => Interval::MinorSecond,

Interval::MajorSecond => Interval::MajorSecond,
Interval::DiminishedThird => Interval::DiminishedThird,

Interval::AugmentedSecond => Interval::AugmentedSecond,
Interval::MinorThird => Interval::MinorThird,

Interval::MajorThird => Interval::MajorThird,
Interval::DiminishedFourth => Interval::DiminishedFourth,

Interval::AugmentedThird => Interval::AugmentedThird,
Interval::PerfectFourth => Interval::PerfectFourth,

Interval::AugmentedFourth => Interval::AugmentedFourth,
Interval::DiminishedFifth => Interval::DiminishedFifth,

Interval::PerfectFifth => Interval::PerfectFifth,
Interval::DiminishedSixth => Interval::DiminishedSixth,

Interval::AugmentedFifth => Interval::AugmentedFifth,
Interval::MinorSixth => Interval::MinorSixth,

Interval::MajorSixth => Interval::MajorSixth,
Interval::DiminishedSeventh => Interval::DiminishedSeventh,

Interval::AugmentedSixth => Interval::AugmentedSixth,
Interval::MinorSeventh => Interval::MinorSeventh,

Interval::MajorSeventh => Interval::MajorSeventh,
Interval::DiminishedOctave => Interval::DiminishedOctave,

Interval::AugmentedSeventh => Interval::AugmentedSeventh,
Interval::PerfectOctave => Interval::PerfectOctave,

Interval::MinorNinth => Interval::MinorSecond,
Interval::MajorNinth => Interval::MajorSecond,
Interval::AugmentedNinth => Interval::AugmentedSecond,

Interval::DiminishedEleventh => Interval::DiminishedFourth,
Interval::PerfectEleventh => Interval::PerfectFourth,
Interval::AugmentedEleventh => Interval::AugmentedFourth,

Interval::MinorThirteenth => Interval::MinorSixth,
Interval::MajorThirteenth => Interval::MajorSixth,
Interval::AugmentedThirteenth => Interval::AugmentedSixth,
}
}
}

0 comments on commit 9c45493

Please sign in to comment.