Feat: adding some basic music theory
This commit is contained in:
@@ -88,6 +88,7 @@ pub enum Op {
|
|||||||
Generate,
|
Generate,
|
||||||
GeomRange,
|
GeomRange,
|
||||||
Times,
|
Times,
|
||||||
|
Chord(&'static [i64]),
|
||||||
// MIDI
|
// MIDI
|
||||||
MidiEmit,
|
MidiEmit,
|
||||||
GetMidiCC,
|
GetMidiCC,
|
||||||
|
|||||||
129
crates/forth/src/theory/chords.rs
Normal file
129
crates/forth/src/theory/chords.rs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
pub struct Chord {
|
||||||
|
pub name: &'static str,
|
||||||
|
pub intervals: &'static [i64],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static CHORDS: &[Chord] = &[
|
||||||
|
// Triads
|
||||||
|
Chord {
|
||||||
|
name: "maj",
|
||||||
|
intervals: &[0, 4, 7],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "m",
|
||||||
|
intervals: &[0, 3, 7],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dim",
|
||||||
|
intervals: &[0, 3, 6],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "aug",
|
||||||
|
intervals: &[0, 4, 8],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "sus2",
|
||||||
|
intervals: &[0, 2, 7],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "sus4",
|
||||||
|
intervals: &[0, 5, 7],
|
||||||
|
},
|
||||||
|
// Seventh chords
|
||||||
|
Chord {
|
||||||
|
name: "maj7",
|
||||||
|
intervals: &[0, 4, 7, 11],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "min7",
|
||||||
|
intervals: &[0, 3, 7, 10],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom7",
|
||||||
|
intervals: &[0, 4, 7, 10],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dim7",
|
||||||
|
intervals: &[0, 3, 6, 9],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "m7b5",
|
||||||
|
intervals: &[0, 3, 6, 10],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "minmaj7",
|
||||||
|
intervals: &[0, 3, 7, 11],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "aug7",
|
||||||
|
intervals: &[0, 4, 8, 10],
|
||||||
|
},
|
||||||
|
// Sixth chords
|
||||||
|
Chord {
|
||||||
|
name: "maj6",
|
||||||
|
intervals: &[0, 4, 7, 9],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "min6",
|
||||||
|
intervals: &[0, 3, 7, 9],
|
||||||
|
},
|
||||||
|
// Extended chords
|
||||||
|
Chord {
|
||||||
|
name: "dom9",
|
||||||
|
intervals: &[0, 4, 7, 10, 14],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "maj9",
|
||||||
|
intervals: &[0, 4, 7, 11, 14],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "min9",
|
||||||
|
intervals: &[0, 3, 7, 10, 14],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom11",
|
||||||
|
intervals: &[0, 4, 7, 10, 14, 17],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "min11",
|
||||||
|
intervals: &[0, 3, 7, 10, 14, 17],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom13",
|
||||||
|
intervals: &[0, 4, 7, 10, 14, 21],
|
||||||
|
},
|
||||||
|
// Add chords
|
||||||
|
Chord {
|
||||||
|
name: "add9",
|
||||||
|
intervals: &[0, 4, 7, 14],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "add11",
|
||||||
|
intervals: &[0, 4, 7, 17],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "madd9",
|
||||||
|
intervals: &[0, 3, 7, 14],
|
||||||
|
},
|
||||||
|
// Altered dominants
|
||||||
|
Chord {
|
||||||
|
name: "dom7b9",
|
||||||
|
intervals: &[0, 4, 7, 10, 13],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom7s9",
|
||||||
|
intervals: &[0, 4, 7, 10, 15],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom7b5",
|
||||||
|
intervals: &[0, 4, 6, 10],
|
||||||
|
},
|
||||||
|
Chord {
|
||||||
|
name: "dom7s5",
|
||||||
|
intervals: &[0, 4, 8, 10],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn lookup(name: &str) -> Option<&'static [i64]> {
|
||||||
|
CHORDS.iter().find(|c| c.name == name).map(|c| c.intervals)
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod chords;
|
||||||
mod scales;
|
mod scales;
|
||||||
|
|
||||||
pub use scales::lookup;
|
pub use scales::lookup;
|
||||||
|
|||||||
@@ -455,7 +455,11 @@ impl Forth {
|
|||||||
let a_f = a.as_float()?;
|
let a_f = a.as_float()?;
|
||||||
let b_f = b.as_float()?;
|
let b_f = b.as_float()?;
|
||||||
let (lo, hi) = if a_f <= b_f { (a_f, b_f) } else { (b_f, a_f) };
|
let (lo, hi) = if a_f <= b_f { (a_f, b_f) } else { (b_f, a_f) };
|
||||||
let val = self.rng.lock().unwrap().gen_range(lo..hi);
|
let val = if (hi - lo).abs() < f64::EPSILON {
|
||||||
|
lo
|
||||||
|
} else {
|
||||||
|
self.rng.lock().unwrap().gen_range(lo..hi)
|
||||||
|
};
|
||||||
stack.push(Value::Float(val, None));
|
stack.push(Value::Float(val, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -629,6 +633,13 @@ impl Forth {
|
|||||||
stack.push(result);
|
stack.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Op::Chord(intervals) => {
|
||||||
|
let root = stack.pop().ok_or("stack underflow")?.as_int()?;
|
||||||
|
for &interval in *intervals {
|
||||||
|
stack.push(Value::Int(root + interval, None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Op::Oct => {
|
Op::Oct => {
|
||||||
let shift = stack.pop().ok_or("stack underflow")?;
|
let shift = stack.pop().ok_or("stack underflow")?;
|
||||||
let note = stack.pop().ok_or("stack underflow")?;
|
let note = stack.pop().ok_or("stack underflow")?;
|
||||||
|
|||||||
@@ -830,6 +830,292 @@ pub const WORDS: &[Word] = &[
|
|||||||
compile: Simple,
|
compile: Simple,
|
||||||
varargs: false,
|
varargs: false,
|
||||||
},
|
},
|
||||||
|
// Chords - Triads
|
||||||
|
Word {
|
||||||
|
name: "maj",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth)",
|
||||||
|
desc: "Major triad",
|
||||||
|
example: "c4 maj => 60 64 67",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "m",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth)",
|
||||||
|
desc: "Minor triad",
|
||||||
|
example: "c4 m => 60 63 67",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dim",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth)",
|
||||||
|
desc: "Diminished triad",
|
||||||
|
example: "c4 dim => 60 63 66",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "aug",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth)",
|
||||||
|
desc: "Augmented triad",
|
||||||
|
example: "c4 aug => 60 64 68",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "sus2",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root second fifth)",
|
||||||
|
desc: "Suspended 2nd",
|
||||||
|
example: "c4 sus2 => 60 62 67",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "sus4",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root fourth fifth)",
|
||||||
|
desc: "Suspended 4th",
|
||||||
|
example: "c4 sus4 => 60 65 67",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
// Chords - Seventh
|
||||||
|
Word {
|
||||||
|
name: "maj7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Major 7th",
|
||||||
|
example: "c4 maj7 => 60 64 67 71",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "min7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Minor 7th",
|
||||||
|
example: "c4 min7 => 60 63 67 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Dominant 7th",
|
||||||
|
example: "c4 dom7 => 60 64 67 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dim7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Diminished 7th",
|
||||||
|
example: "c4 dim7 => 60 63 66 69",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "m7b5",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Half-diminished (min7b5)",
|
||||||
|
example: "c4 m7b5 => 60 63 66 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "minmaj7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Minor-major 7th",
|
||||||
|
example: "c4 minmaj7 => 60 63 67 71",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "aug7",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh)",
|
||||||
|
desc: "Augmented 7th",
|
||||||
|
example: "c4 aug7 => 60 64 68 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
// Chords - Sixth
|
||||||
|
Word {
|
||||||
|
name: "maj6",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth sixth)",
|
||||||
|
desc: "Major 6th",
|
||||||
|
example: "c4 maj6 => 60 64 67 69",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "min6",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth sixth)",
|
||||||
|
desc: "Minor 6th",
|
||||||
|
example: "c4 min6 => 60 63 67 69",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
// Chords - Extended
|
||||||
|
Word {
|
||||||
|
name: "dom9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth)",
|
||||||
|
desc: "Dominant 9th",
|
||||||
|
example: "c4 dom9 => 60 64 67 70 74",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "maj9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth)",
|
||||||
|
desc: "Major 9th",
|
||||||
|
example: "c4 maj9 => 60 64 67 71 74",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "min9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth)",
|
||||||
|
desc: "Minor 9th",
|
||||||
|
example: "c4 min9 => 60 63 67 70 74",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom11",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth eleventh)",
|
||||||
|
desc: "Dominant 11th",
|
||||||
|
example: "c4 dom11 => 60 64 67 70 74 77",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "min11",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth eleventh)",
|
||||||
|
desc: "Minor 11th",
|
||||||
|
example: "c4 min11 => 60 63 67 70 74 77",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom13",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh ninth thirteenth)",
|
||||||
|
desc: "Dominant 13th",
|
||||||
|
example: "c4 dom13 => 60 64 67 70 74 81",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
// Chords - Add
|
||||||
|
Word {
|
||||||
|
name: "add9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth ninth)",
|
||||||
|
desc: "Major add 9",
|
||||||
|
example: "c4 add9 => 60 64 67 74",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "add11",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth eleventh)",
|
||||||
|
desc: "Major add 11",
|
||||||
|
example: "c4 add11 => 60 64 67 77",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "madd9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth ninth)",
|
||||||
|
desc: "Minor add 9",
|
||||||
|
example: "c4 madd9 => 60 63 67 74",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
// Chords - Altered dominants
|
||||||
|
Word {
|
||||||
|
name: "dom7b9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh flatninth)",
|
||||||
|
desc: "7th flat 9",
|
||||||
|
example: "c4 dom7b9 => 60 64 67 70 73",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom7s9",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third fifth seventh sharpninth)",
|
||||||
|
desc: "7th sharp 9 (Hendrix chord)",
|
||||||
|
example: "c4 dom7s9 => 60 64 67 70 75",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom7b5",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third flatfifth seventh)",
|
||||||
|
desc: "7th flat 5",
|
||||||
|
example: "c4 dom7b5 => 60 64 66 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
|
Word {
|
||||||
|
name: "dom7s5",
|
||||||
|
aliases: &[],
|
||||||
|
category: "Chord",
|
||||||
|
stack: "(root -- root third sharpfifth seventh)",
|
||||||
|
desc: "7th sharp 5",
|
||||||
|
example: "c4 dom7s5 => 60 64 68 70",
|
||||||
|
compile: Simple,
|
||||||
|
varargs: true,
|
||||||
|
},
|
||||||
// LFO
|
// LFO
|
||||||
Word {
|
Word {
|
||||||
name: "ramp",
|
name: "ramp",
|
||||||
@@ -2676,6 +2962,11 @@ pub(super) fn compile_word(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(intervals) = theory::chords::lookup(name) {
|
||||||
|
ops.push(Op::Chord(intervals));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(word) = lookup_word(name) {
|
if let Some(word) = lookup_word(name) {
|
||||||
match &word.compile {
|
match &word.compile {
|
||||||
Simple => {
|
Simple => {
|
||||||
|
|||||||
@@ -54,3 +54,6 @@ mod generator;
|
|||||||
|
|
||||||
#[path = "forth/midi.rs"]
|
#[path = "forth/midi.rs"]
|
||||||
mod midi;
|
mod midi;
|
||||||
|
|
||||||
|
#[path = "forth/chords.rs"]
|
||||||
|
mod chords;
|
||||||
|
|||||||
178
tests/forth/chords.rs
Normal file
178
tests/forth/chords.rs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
use cagire::forth::Value;
|
||||||
|
|
||||||
|
use super::harness::{expect_stack, run};
|
||||||
|
|
||||||
|
fn ints(vals: &[i64]) -> Vec<Value> {
|
||||||
|
vals.iter().map(|&v| Value::Int(v, None)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triads
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_major() {
|
||||||
|
expect_stack("c4 maj", &ints(&[60, 64, 67]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_minor() {
|
||||||
|
expect_stack("c4 m", &ints(&[60, 63, 67]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_diminished() {
|
||||||
|
expect_stack("c4 dim", &ints(&[60, 63, 66]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_augmented() {
|
||||||
|
expect_stack("c4 aug", &ints(&[60, 64, 68]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_sus2() {
|
||||||
|
expect_stack("c4 sus2", &ints(&[60, 62, 67]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_sus4() {
|
||||||
|
expect_stack("c4 sus4", &ints(&[60, 65, 67]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seventh chords
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_maj7() {
|
||||||
|
expect_stack("c4 maj7", &ints(&[60, 64, 67, 71]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_min7() {
|
||||||
|
expect_stack("c4 min7", &ints(&[60, 63, 67, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom7() {
|
||||||
|
expect_stack("c4 dom7", &ints(&[60, 64, 67, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dim7() {
|
||||||
|
expect_stack("c4 dim7", &ints(&[60, 63, 66, 69]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_half_dim() {
|
||||||
|
expect_stack("c4 m7b5", &ints(&[60, 63, 66, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_minmaj7() {
|
||||||
|
expect_stack("c4 minmaj7", &ints(&[60, 63, 67, 71]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_aug7() {
|
||||||
|
expect_stack("c4 aug7", &ints(&[60, 64, 68, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sixth chords
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_maj6() {
|
||||||
|
expect_stack("c4 maj6", &ints(&[60, 64, 67, 69]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_min6() {
|
||||||
|
expect_stack("c4 min6", &ints(&[60, 63, 67, 69]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extended chords
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom9() {
|
||||||
|
expect_stack("c4 dom9", &ints(&[60, 64, 67, 70, 74]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_maj9() {
|
||||||
|
expect_stack("c4 maj9", &ints(&[60, 64, 67, 71, 74]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_min9() {
|
||||||
|
expect_stack("c4 min9", &ints(&[60, 63, 67, 70, 74]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom11() {
|
||||||
|
expect_stack("c4 dom11", &ints(&[60, 64, 67, 70, 74, 77]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_min11() {
|
||||||
|
expect_stack("c4 min11", &ints(&[60, 63, 67, 70, 74, 77]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom13() {
|
||||||
|
expect_stack("c4 dom13", &ints(&[60, 64, 67, 70, 74, 81]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add chords
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_add9() {
|
||||||
|
expect_stack("c4 add9", &ints(&[60, 64, 67, 74]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_add11() {
|
||||||
|
expect_stack("c4 add11", &ints(&[60, 64, 67, 77]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_madd9() {
|
||||||
|
expect_stack("c4 madd9", &ints(&[60, 63, 67, 74]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Altered dominants
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom7b9() {
|
||||||
|
expect_stack("c4 dom7b9", &ints(&[60, 64, 67, 70, 73]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom7s9() {
|
||||||
|
expect_stack("c4 dom7s9", &ints(&[60, 64, 67, 70, 75]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom7b5() {
|
||||||
|
expect_stack("c4 dom7b5", &ints(&[60, 64, 66, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_dom7s5() {
|
||||||
|
expect_stack("c4 dom7s5", &ints(&[60, 64, 68, 70]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Different roots
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_a3_min7() {
|
||||||
|
expect_stack("a3 min7", &ints(&[57, 60, 64, 67]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_e4_dom7s9() {
|
||||||
|
expect_stack("e4 dom7s9", &ints(&[64, 68, 71, 74, 79]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chord_with_integer_root() {
|
||||||
|
let f = run("60 maj");
|
||||||
|
let stack = f.stack();
|
||||||
|
assert_eq!(stack, ints(&[60, 64, 67]));
|
||||||
|
}
|
||||||
@@ -171,3 +171,8 @@ fn logrand_requires_positive() {
|
|||||||
expect_error("-1.0 10.0 logrand", "logrand requires positive values");
|
expect_error("-1.0 10.0 logrand", "logrand requires positive values");
|
||||||
expect_error("1.0 0.0 logrand", "logrand requires positive values");
|
expect_error("1.0 0.0 logrand", "logrand requires positive values");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rand_equal_bounds() {
|
||||||
|
expect_float("5.0 5.0 rand", 5.0);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user