Skip to main content

music21_rs/figuredbass/
rules.rs

1//! What a figured-bass realization is held to: music21's
2//! `figuredBass.rules`.
3
4use crate::defaults::IntegerType;
5use crate::pitch::Pitch;
6
7/// The rules a realization keeps, each on or off: which voicings of one
8/// chord are acceptable, which moves from one chord to the next are, and
9/// how the chords that must resolve a particular way are resolved.
10///
11/// Every rule starts out as music21's does.
12#[derive(Clone, Debug, PartialEq)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub struct Rules {
15    /// Refuse a voicing that leaves out a note of its chord.
16    pub forbid_incomplete_possibilities: bool,
17    /// How far apart, in semitones, the upper parts may lie; `None` lets
18    /// them lie anywhere.
19    pub upper_parts_max_semitone_separation: Option<IntegerType>,
20    /// Refuse a voicing where a part sings above a part over it.
21    pub forbid_voice_crossing: bool,
22    /// Refuse parallel fifths.
23    pub forbid_parallel_fifths: bool,
24    /// Refuse parallel octaves.
25    pub forbid_parallel_octaves: bool,
26    /// Refuse hidden fifths between the outer parts.
27    pub forbid_hidden_fifths: bool,
28    /// Refuse hidden octaves between the outer parts.
29    pub forbid_hidden_octaves: bool,
30    /// Refuse a part moving past where a neighbouring part was.
31    pub forbid_voice_overlap: bool,
32    /// How far each part named may move, in semitones: `(part, semitones)`,
33    /// counting the highest part as one.
34    pub part_movement_limits: Vec<(usize, IntegerType)>,
35    /// Resolve a dominant seventh as a dominant seventh resolves.
36    pub resolve_dominant_seventh_properly: bool,
37    /// Resolve a diminished seventh as a diminished seventh resolves.
38    pub resolve_diminished_seventh_properly: bool,
39    /// Resolve an augmented sixth as an augmented sixth resolves.
40    pub resolve_augmented_sixth_properly: bool,
41    /// Resolve a diminished seventh to the tonic with its root doubled,
42    /// rather than its third, where the inversions do not decide it.
43    pub doubled_root_in_dim7: bool,
44    /// Hold a special resolution to the rules for single voicings too.
45    pub apply_single_possib_rules_to_resolution: bool,
46    /// Hold a special resolution to the rules for moving between voicings
47    /// too.
48    pub apply_consecutive_possib_rules_to_resolution: bool,
49    /// In resolving an Italian sixth, let the root resolve only once and
50    /// the third not be doubled.
51    pub restrict_doublings_in_italian_a6_resolution: bool,
52    /// Keep every part but the bass where it was: music21's
53    /// `_upperPartsRemainSame`, which a realizer sets for a bass note that
54    /// only moves.
55    pub upper_parts_remain_same: bool,
56    /// Hold each part named to a pitch: `(part, pitch)`, counting the
57    /// highest part as one. music21's `_partPitchLimits`.
58    pub part_pitch_limits: Vec<(usize, Pitch)>,
59    /// The parts that must keep their pitch from one voicing to the next:
60    /// music21's `_partsToCheck`.
61    pub parts_to_check: Vec<usize>,
62}
63
64impl Default for Rules {
65    fn default() -> Self {
66        Self {
67            forbid_incomplete_possibilities: true,
68            upper_parts_max_semitone_separation: Some(12),
69            forbid_voice_crossing: true,
70            forbid_parallel_fifths: true,
71            forbid_parallel_octaves: true,
72            forbid_hidden_fifths: true,
73            forbid_hidden_octaves: true,
74            forbid_voice_overlap: true,
75            part_movement_limits: Vec::new(),
76            resolve_dominant_seventh_properly: true,
77            resolve_diminished_seventh_properly: true,
78            resolve_augmented_sixth_properly: true,
79            doubled_root_in_dim7: false,
80            apply_single_possib_rules_to_resolution: false,
81            apply_consecutive_possib_rules_to_resolution: false,
82            restrict_doublings_in_italian_a6_resolution: true,
83            upper_parts_remain_same: false,
84            part_pitch_limits: Vec::new(),
85            parts_to_check: Vec::new(),
86        }
87    }
88}