///|
fn simultaneous(a : Note, b : Note) -> Bool {
a.onset == b.onset
}
///|
fn min_int(a : Int, b : Int) -> Int {
if a < b {
a
} else {
b
}
}
///|
fn add_vertical_findings(
cantus : Array[Note],
counter : Array[Note],
options : AnalysisOptions,
out : Array[Finding],
) -> Unit {
let n = min_int(cantus.length(), counter.length())
for i in 0.. Unit {
let n = min_int(cantus.length(), counter.length())
if n < 2 {
return
}
for i in 1.. Unit {
let n = min_int(cantus.length(), counter.length())
if n < 2 {
return
}
let final_interval = interval_class(
harmonic_interval(cantus[n - 1], counter[n - 1]),
)
if final_interval != 0 && final_interval != 7 {
out.push(
Finding::warning(
rule=CadenceShape,
index=n - 1,
message="final sonority is expected to be octave/unison or fifth",
),
)
}
}
///|
pub fn analyze_harmony(
cantus : Array[Note],
counter : Array[Note],
options : AnalysisOptions,
) -> Array[Finding] {
let out : Array[Finding] = []
add_vertical_findings(cantus, counter, options, out)
add_motion_findings(cantus, counter, out)
if options.strict_cadence {
add_cadence_finding(cantus, counter, out)
}
out
}