Exemplo n.º 1
0
def forbid_false_relation_tritone(s1,s2,allow_in_minor=False):
    """
    Warn if tritone false relation is found
    """
    msg = f"False relation of tritone is forbidden. In {s1.title} and {s2.title}"
    def __fun(n1, n2):
        n1p, n2p = [util.to_pitch(x) for x in (n1,n2)]
        def __is_VI_VII_minor():
            if allow_in_minor is not True:
                return False
            if s1.scale.mode == scale.Mode.m_rising:
                _scale = s1.scale.mode
            elif s1.scale.mode == scale.Mode.m_full:
                _scale = s1.scale.minor_scales[scale.Mode.m_rising]
            elif s1.scale.mode == scale.Mode.M:
                _scale = s1.scale.mode.relative(scale.Mode.m_rising)
            else:
                return False 
            try:
                return _scale.isDegree(n1p,6) or _scale.isDegree(n1p,7) or _scale.isDegree(n2p,6) or _scale.isDegree(n2p,7)
            except ValueError:
                return False

        if n1p.isTritoneWith(n2p) and not __is_VI_VII_minor():
            error.warn(msg,n1,n2)

    for (na, n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,all=True)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]
        __fun(na,n2)
        __fun(n1,nb)
Exemplo n.º 2
0
def rule_6(data):
    """Les voix ne doivent pas toutes effectuer le même mouvement, sauf si on enchaîne deux accords de sixtes."""
    for group1, group2 in util.pairwise(tools.iter_melodies(*data)):
        try:
            assert len(group1) == len(group2) and "Error : pauses not handled"
        except:
            from IPython import embed;embed()
        is_same_mov =  True
        for i in range(len(group1)):
            for j in range(i+1,len(group1)):
                notes1 = sorted(util.to_pitch([group1[i],group1[j]]),key=lambda x : x.value.semitone)
                notes2 = sorted(util.to_pitch([group2[i],group2[j]]),key=lambda x : x.value.semitone)
                if motion.MotionType.motion(*notes1,*notes2) is not motion.MotionType.direct:
                    is_same_mov = False
                    break
            if is_same_mov is False:
                break

        if is_same_mov:
            # are there 2 consecutive sixth?
            pos1 = max(group1,key=lambda x:x.pos).pos
            scale1 = data[0].scaleAt(pos1)
            c1 = chord.AbstractChord.findBestChord(group1,scale1)
            pos2 = max(group2,key=lambda x:x.pos).pos
            scale2 = data[0].scaleAt(pos2)
            c2 = chord.AbstractChord.findBestChord(group2,scale2)

            if not (c1.isInversion(group1,1) and c2.isInversion(group2,1)):
                warn(f"All the voices shouldn't be in the same direction.",group1,group2)
Exemplo n.º 3
0
def rule_19(data):
    """On ne supprime pas la tierce"""
    for notes in tools.iter_melodies(*data,all=True):
        pos = max(notes,key=lambda x:x.pos).pos
        c = chord.AbstractChord.findBestChord(notes,data[0].scaleAt(pos))
        if not c.hasThird(notes):
            warn(f"In a chord, the third must be present: ",notes)
Exemplo n.º 4
0
def rule_16(s1,s2):
    """Les croisements sont interdits"""
    is_s1_higher = s1.notes[0].pitch > s2.notes[0].pitch
    for n1, n2 in tools.iter_melodies(s1,s2):
        p1,p2 = [util.to_pitch(n) for n in (n1,n2)]
        if (is_s1_higher and p2 > p1) or (not is_s1_higher and p1 > p2):
            warn(f"Intersection is forbidden",n1,n2,s1.title,s2.title)
Exemplo n.º 5
0
def forbid_consecutive_interval(s1, s2, interval):
    """Warn if two intervals of the same type are consecutive
    Interval must be qualified"""
    for (na,n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,all=True)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]
        if nap.isQualifiedInterval(interval).With(n1p) and nbp.isQualifiedInterval(interval).With(n2p):
            error.warn(f"Two {interval} in a row are forbidden",na,nb,n1,n2,f"in {s1.title} and {s2.title}")
Exemplo n.º 6
0
def rule_22(data):
    """La quarte et sixte doit être préparée, c’est-à-dire que l’une des deux notes formant la quarte doit se trouver à l’accord précédent et se prolonger par syncope dans l’accord de quarte et sixte.
    La sixte et quarte sur dominante (deuxième renversement de l’accord de tonique) n’a pas besoin d’être préparée, même si c’est la dominante d’un nouveau ton.
    Dans l’accord de sixte sensible (deuxième renversement), il n’est pas absolument nécessaire de préparer la quarte contrairement à l’accord de quarte et sixte.
    """
    for notes in tools.iter_melodies(*data):
        c = chord.AbstractChord.findBestChordFromStave(notes,data[0])
        # is it a 2nd inversion chord?
        if not c.isInversion(notes,2):
            continue
        # is it a chord on dominant?
        pos = max(notes,key=lambda x : x.pos).pos
        current_scale = data[0].scaleAt(pos)
        bass = [n for n in notes if c.isFifth(n)][0]
        if current_scale.isDominant(bass.pitch):
            continue
        # is it the 2nd inversion chord of a 7th dominant chord?
        if c.hasSeventh(notes) and c.degree == 5:
            continue
        # is one of the notes prepared?
        is_prepared = False
        for n in notes:
            if (c.isFifth(n) or c.isRoot(n) ) and n.pos < pos:
                is_prepared = True
                break
        if is_prepared:
            continue
        else:
            warn(f"In a 2nd inversion chord, one of the notes of the fourth (the root or the fifth of the chord) must be present in the previous chord at the pitch and the same voice and joined to the note in the chord by syncopation, except for a chord which bass is the dominant: in that case, it is not necessary to prepare it.",notes)
Exemplo n.º 7
0
def forbid_sequence(*s,min_len=2):
    """Forbids sequences in staves s.
    There must be at least one stave
    """
    assert len(s) >= 1
    notes = [part for part in tools.iter_melodies(*s)]

    for start in range(len(notes)):
        for end in range(start,len(notes)):
            if end - start < min_len:
                continue

            # try a motif
            motif = []
            for i in range(start,end+1):
                motif.extend(notes[i])

            # try a following
            part_nb = end - start + 1
            try:
                following = []
                for i in range(end+1, part_nb + end + 1):
                    following.extend(notes[i])
            except IndexError:
                break

            # is there a sequence?
            try:
                if tools.matchSequence(motif, following, s[0].scale):
                    warn(f"Sequence in {(s.title for s in s)}.",motif,following)
            except ValueError:
                continue
Exemplo n.º 8
0
def rule_23(data):
    """
    La quarte doit être sauvée : soit la note supérieure reste en place ou descend d’un degré ; soit la basse reste en place.
    """
    for group1, group2 in util.pairwise(tools.iter_melodies(*data)):
        c = chord.AbstractChord.findBestChordFromStave(group1,data[0])
        if not c.isInversion(group1,2):
            continue
        last_pos = min(group1,key=lambda x : x.last_pos).last_pos
        is_correct = False
        for n,n2 in zip(group1,group2):
            if c.isFifth(n) and n.last_pos > last_pos:
                is_correct = True
                break
            elif c.isRoot(n):
                if (n.last_pos > last_pos):
                    is_correct = True
                    break
                elif n.pitch > n2.pitch and n.pitch.isConjunctWith(n2.pitch):
                    is_correct = True
                    break
        if is_correct:
            continue
        else:
            warn(f"In a 2nd inversion chord, the root must go to lower degree by conjunct motion, or must continue by syncopation, or the 5th must continue by syncopation",group1)
Exemplo n.º 9
0
def rule_4(cp,cf):
    """Le temps fort doit être en consonance. Il sera toléré, dans les cas difficiles, de placer la dissonance au temps fort, à la condition qu'elle se produise dans la forme de broderie ou de note de passage et que les deux parties procèdent par mouvement contraire et par degrés conjoints"""
    # in this function, we do not look at the first note if the first note is at the downbeat, for it is already checked by function rule_3
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        # is it downbeat?
        if cp.isUpBeat(n2):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        #is it a consonance?
        if n2p.isConsonantWith(nbp):
            continue
        #is it a cambiata or a passing tone?
        is_pt_or_c = cp.isCambiata(n2,False) or cp.isPassingTone(n2,False)
        #is it a conjunct movement?
        is_conjunct = cp.isConjunct(n2)
        #is it a contray motion?
        first = [n1p,nap]
        second = [n2p,nbp]
        first.sort(key=lambda x : x,reverse=True)
        second.sort(key=lambda x : x,reverse=True)
        is_contrary = motion.MotionType.motion(*first,*second) == motion.MotionType.contrary

        warn(f"""The downbeat is dissonant. It must be:
        - a cambiata or passing tone: {is_pt_or_c}
        - come from a conjunct motion: {is_conjunct}
        - come from a contrary motion: {is_contrary}
        """,cp.title,n2)
Exemplo n.º 10
0
def rule_8(s1,s2,min=pitch.Pitch.F3):
    """Les tierces dans le grave sont lourdes et à éviter.
    Here, we choose to warn if the third is under F3"""
    for n1, n2 in tools.iter_melodies(s1,s2):
        np1,np2 = util.to_pitch((n1,n2))
        if np1.isInterval(3).With(np2) and (np1 < min and np2 < min):
            warn(f"Low thirds should be avoided",n1,n2,s1.title,s2.title)
Exemplo n.º 11
0
def rule_13(cp,cf):
    """Éviter la broderie ou la note de passage qui produit l'intervalle de seconde mineure avec le chant donné"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        if not (cp.isCambiata(n2) or cp.isPassingTone(n2)):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if n2p.semitoneWith(nbp) == 1:
            warn(f"Avoid minor seconds",cp.title,n2)
Exemplo n.º 12
0
def rule_5(cp, cf):
    """Le temps faible peut être en consonance ou en dissonance, pourvu que la dissonance se produise par degrés conjoints"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        if not cp.isUpBeat(n2):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if not n2p.isConsonantWith(nbp):
            if not cp.isConjunct(n2):
                warn(f"If the upbeat is dissonant, it must come from a conjunct motion.",cp.title,n2)
Exemplo n.º 13
0
def rule_26(soprano,bass): 
    """
    La quinte directe entre parties extrêmes par modulation et mouvement chromatique est prohibée.
    """
    # TODO on ne vérifie pas s'il y a une quinte...
    for (h1,l1), (h2,l2) in util.pairwise(tools.iter_melodies(soprano,bass)):
        mot = motion.MotionType.motion(h1,l1,h2,l2)
        if mot == motion.MotionType.direct and (h1.pitch.isChromaticInflectionWith(h2.pitch) or l1.pitch.isChromaticInflectionWith(l2.pitch)):
            warn(f"A direct fifth by modulation and chromatic motion is forbidden between extreme parts",h1,h2,l1,l2,soprano.title,bass.title)
Exemplo n.º 14
0
def forbid_direct_interval(s1, s2, *intervals):
    """Warns if interval occured by direct motion
    intervals must be qualified or not """
    for (na,n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,all=True)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]

        answer = nbp.isQualifiedInterval(*intervals).With(n2p) if not isinstance(intervals[0],int) else nbp.isInterval(*intervals,True).With(n2p)

        if answer and (motion.MotionType.motion(na,n1,nb,n2) == motion.MotionType.direct):
            error.warn(f"It is forbidden to go to direct {intervals}",na,nb,n1,n2,f"in {s1.title} and {s2.title}")
Exemplo n.º 15
0
def rule_7(cp, cf):
    """Lorsqu'une broderie forme dissonance attractive de quarte augmentée ou de quinte diminuée, et qu'elle retourne sur la note consonante qui l'a précédée, elle est à éviter. Cette règle est applicable aussi à la dissonance de quarte et, avec plus de tolérance, à celles de seconde et de septième"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        if not cp.isCambiata(n2):
            continue
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if n2p.isQualifiedInterval((5,"diminished"),(4,"augmented"),(4,"perfect")).With(nbp) and n1p.isConsonantWith(nap):
            warn(f"It is forbidden to have a cambiata having an interval of 5th diminished, 4th perfect or augmented that return to a consonant pitch", cp.title,n2)

        elif n2p.isInterval(2,7,True).With(nbp) and n1p.isConsonantWith(nap):
            warn(f"If the cambiata forms a seventh or a second with the other voice, it can return to the consonant note by tolerance only",cp.title,n2)
Exemplo n.º 16
0
def rule_8(cp, cf):
    """L'unisson est toléré au temps faible"""
    for n1, n2 in tools.iter_melodies(cp,cf,alone=False):
        if n1.pitch == n2.pitch:
            if n1 in (cp[-1],cp[0]):
                # it is the last or the first, which can be an unison
                continue
            if cp.isUpBeat(n1):
                warn(f"There is tolerance for unison if the note is upbeat. {cp.title}",n1)
            else:
                warn(f"Unison is forbidden if the note is downbeat. {cp.title}",n1)
Exemplo n.º 17
0
def intersection(s1, s2):
    """True if the two melodies intersect.
    Warn at every point intersection is found"""
    state = None
    for notes in tools.iter_melodies(s1,s2):
        pnotes = [util.to_pitch(n) for n in notes]
        if len(notes) == 1 or pnotes[0] == pnotes[1]:
            continue
        new_state = pnotes[0] < pnotes[1]
        if state is not None and new_state is not state:
            error.warn(f"Melodies intersect.",*notes)
        state = new_state
Exemplo n.º 18
0
def rule_14(data):
    """Les octaves et quintes par mouvement direct ne sont autorisées que si la voix supérieure procède par mouvement conjoint.
        La quinte directe est tolérable si la voix inférieure procède par mouvement conjoint, à condition que l’une des voix soit le ténor ou le contralto et que la voix inférieure aboutisse à un des bons degrés (I – IV – V) de la gamme.
    La quinte directe est tolérable si l’une des notes de la quinte appartient à l’accord précédent, même par mouvement disjoint, à condition qu’elle ait une bonne sonorité.
    À l’intérieur d’un même accord, on tolère des quintes et des octaves directes, y compris par mouvement direct et disjoint.
    """
    chords = chord.RealizedChord.chordify(data)
    extreme_titles = data[0].title, data[-1].title
    for s1,s2 in itertools.combinations(data,2):
        for (n1,n2), (na, nb) in util.pairwise(tools.iter_melodies(s1,s2)):
            # is it a fifth or an octave?
            if not na.pitch.isQualifiedInterval((8,'perfect'),(5,'perfect'),(5,'diminished'),(5,'augmented')).With(nb.pitch):
                continue
            # is it in the same chord?
            for c in chords:
                if (n1,n2,na,nb) in c:
                    continue
            # is it a direct 5th or octave?
            if motion.MotionType.motion(n1,n2,na,nb) != motion.MotionType.direct:
                continue
            # does the upper voice proceed by conjunct movement?
            if n1.pitch.semitoneWith(na.pitch) in (1,2):
                continue
            # if it is an octave, there's no more tolerance: it's an error
            if na.pitch.isInterval(8,True).With(nb.pitch):
                warn(f"Direct octaves with no conjunct movement is forbidden.",n1,n2,na,nb,s1.title, s2.title)
                continue
            # is it a direct 5th with lower voice going to I, IV or V
            # by conjunct movement in non extreme parts?
            if extreme_titles != (s1.title, s2.title):
                # get scale of the second interval: there may be a modulation between the 2 intervals.
                pos = max(na.pos,nb.pos)
                current_scale = s2.scaleAt(pos)
                if n2.pitch.semitoneWith(nb.pitch) in (1,2) and current_scale.is1_4_5(nb.pitch) :
                    warn(f"Tolerance: direct fith with lower voice going to I, IV, V by conjunct movement between non extreme parts is tolerated. Do not hesitate to find a better disposition",n1,n2,na,nb,s1.title,s2.title)
                    continue
            # is it a direct 5th with a note of the 5th in the previous chord?
            broken=False
            for c1, c2 in util.pairwise(chords):
                if (na, nb) in c2 and (na in c1 or nb in c1):
                    warn(f"Tolerance: direct fifth is tolerated if one of the notes of the 5th can be heard in the previous chord AND if the sound is good. Please check that.",n1,n2, na,nb, s1.title,s2.title)
                    broken=True
                    break
            if broken:
                continue
            # error
            warn(f"""Direct 5th are forbidden, except:
            - when the higher voice moves by conjunct motion
            - when, except in extreme parts, the lower voice moves by conjunct motion to I, IV, V
            - when the note of the 5th can be heard in the previous chord
            - in a change of position inside a chord.
            """, n1,n2, na,nb,s1.title,s2.title)
Exemplo n.º 19
0
def calculate_motion_types(s1, s2):
    """Finds the number of motion type: direct, contrary
    and oblique"""
    movs = { motion.MotionType.direct : 0,
            motion.MotionType.contrary : 0,
            motion.MotionType.oblique : 0,
            motion.MotionType.no:0}

    for (na,n1), (nb, n2) in util.pairwise(tools.iter_melodies(s1,s2,alone=False)):
        nap, nbp, n1p, n2p = [util.to_pitch(x) for x in (na, nb, n1, n2)]
        movs[motion.MotionType.motion(nap,n1p,nbp,n2p)] += 1

    return movs
Exemplo n.º 20
0
def rule_9(s1,s2):
    """
    1. Le soprano et le contralto ne doivent pas être éloignés de la voix inférieure d’un intervalle supérieur à l’octave.
    2. Le ténor et la basse ne doivent pas être éloignés d’un intervalle supérieur à la douzième.
    3. Il est possible d’excéder l’intervalle maximal dans le cas d’un saut d’octave, de préférence suivi d’un mouvement mélodique inverse.
    """
    titles = (s1.title,s2.title)
    max = 12 if titles == ("Tenor","Bass") else 8

    for n1, n2 in tools.iter_melodies(s1,s2):
        np1,np2 = util.to_pitch((n1,n2))
        if np1.intervalWith(np2) > max:
            warn(f"Max interval between {s1.title} and {s2.title} is {max}, except if there's a melodic octave, or other thing of that kind followed by a melodic contrary movement. Is that the case?",n1,n2,*titles)
Exemplo n.º 21
0
def rule_7(data):
    """Il est interdit de doubler la sensible. Pour les accords de 7ème de dominante, une exception est faite et cette question est traitée dans la règle 33"""
    st = tools.SequenceTracker(data)
    for notes in tools.iter_melodies(*data):
        # get scale
        pos = max([n.pos for n in notes])
        sc = data[0].scaleAt(pos)
        leadings = [n for n in notes if sc.isLeading(n.pitch) and not st.isInRestatement(n)]
        current_chord = chord.AbstractChord.findBestChord(notes,sc)
        # is it a 7th dominant chord?
        if current_chord.hasSeventh(notes) and current_chord.degree == 5:
            continue
        if len(leadings) > 1:
            warn(f"The leading tone can not be doubled, except in a restatement of a sequence",*notes)
Exemplo n.º 22
0
def rule_20(data):
    """La fausse relation de triton est proscrite."""
    st = tools.SequenceTracker(data)
    for notes1, notes2 in util.pairwise(tools.iter_melodies(*data,alone=False)):
        clef = lambda n : n.pitch
        h1 = max(notes1,key=clef)
        l1 = min(notes1,key=clef)
        h2 = max(notes2,key=clef)
        l2 = min(notes2,key=clef)
        if h1 == h2 or l1 == l2:
            continue
        if ((h1.pitch.isTritoneWith(l2.pitch) or l1.pitch.isTritoneWith(h2.pitch)) and
                (not st.isInRestatement(h1) and not st.isInRestatement(h2))):
            warn(f"False relation of tritone is forbidden between extreme parts, except inside the restatement in a sequence.",notes1,notes2)
Exemplo n.º 23
0
def rule_25(s1,s2):
    """
    1. La fausse relation chromatique est prohibée. À distance, elle peut être bonne.
    2. Tout changement chromatique s’effectue dans la même partie.
    3. Il est interdit de doubler la note qui est modifiée chromatiquement dans les deux accords.
    4. On tolère le doublement de la note caractéristique si on aboutit à la note chromatique par mouvement contraire.
    """
    warn(f"Please check by ear that there are no distant false relations")
    for (h1,l1), (h2,l2) in util.pairwise(tools.iter_melodies(s1,s2)):
        if (h1.pitch.isChromaticInflectionWith(l2.pitch,min=True) or l1.pitch.isChromaticInflectionWith(h2.pitch,min=True)):
            if (h1.pitch.isSameNote(l1.pitch) or h2.pitch.isSameNote(l2.pitch)) and motion.MotionType.motion(h1,l1,h2,l2) == motion.MotionType.contrary:
                text = "Doubling one of the notes of a chromatism when there's a contrary motion is only tolerated."
            else:
                text = "It is forbidden to do a chromatic false relation"
            warn(text,h1,l1,h2,l2,s1.title,s2.title)
Exemplo n.º 24
0
def by_two_intervals(s1,s2,interval):
    """Similar to distance_between_intervals,
    but yield only the two intervals
    """
    def fun(x,y):
        if isinstance(interval,int):
            return x.pitch.isInterval(interval,True).With(y.pitch)
        return x.pitch.isQualifiedInterval(interval).With(y.pitch)

    previous_interval = None
    for n1, n2 in tools.iter_melodies(s1,s2,alone=False):
        if fun(n1,n2):
            if previous_interval is None:
                previous_interval = n1,n2
                continue
            yield previous_interval, (n1,n2)
            previous_interval = n1,n2
Exemplo n.º 25
0
def rule_21(data):
    """
    Dans les accords de sixte, il est interdit de doubler la basse, sauf si :
        1. la basse est l’un des bons degrés (I – IV – V) ;
        2. lors d’un changement de position ; // TODO send a warning
        3. si on arrive à la basse et à sa doublure par mouvement contraire et conjoint (fa et la vers sol, par exemple)
    """
    for group1, group2 in util.pairwise(tools.iter_melodies(*data)):
        c2 = chord.AbstractChord.findBestChordFromStave(group2,data[0])
        # is it a 6th chord?
        if not c2.isInversion(group2,1):
            continue
        # is the bass doubled?
        basses = [x for x in group2 if c2.isPosition(x,3)]
        if len(basses) <= 1:
            continue
        # is the bass I,IV or V?
        bass = sorted(group2,key=lambda n:n.pitch)[0]
        pos = max(group2,key=lambda n : n.pos).pos
        current_scale = data[0].scaleAt(pos)
        if current_scale.is1_4_5(bass.pitch):
            continue
        # is the bass in a change of position?
        c1 = chord.AbstractChord.findBestChordFromStave(group1,data[0])
        if c1 == c2:
            warn(f"It is possible, but potentially not really good to double the bass of a sixth chord when the notes change their position in the chord.",group2)
            continue
        # is the movement to the bass and its octave conjunct and contrary?
        ## is the note of the bass found more than 2 times?
        if len(basses) > 2:
            warn(f"It is not possible to double more than 2 times the bass in a 6th chord.",group2)
            continue
        indices = [group2.index(n) for n in basses]
        previous_notes = [n for i,n in enumerate(group1) if i in indices]
        if (motion.MotionType.motion(*previous_notes,*basses) == motion.MotionType.contrary ) and previous_notes[0].pitch.isConjunctWith(basses[0].pitch) and previous_notes[1].pitch.isConjunctWith(basses[1].pitch):
            warn(f"It is possible to double the bass by conjunct and contrary motion",group1,group2)
            continue

        # error
        warn(f"""It is forbidden to double the bass of a sixth chord, except when:
        - the bass is I, IV, V,
        - there is a change of position in the chord
        - there is a conjunct and contrary motion to the bass and its octave.""",
        group2)
Exemplo n.º 26
0
def rule_15(s1,s2):
    """L'unisson est interdit
    Dans les accords parfaits, l'unisson peut être toléré:
        - sur les temps faibles,
        - en cas de saut d'octave
        - si la basse monte haut
        - si le soprano descend bas
        - mais l'unisson ténor-alto est très maladroit.
    """
    for n1, n2 in tools.iter_melodies(s1,s2):
        p1,p2 = [util.to_pitch(n) for n in (n1,n2)]
        if p1 == p2:
            warn(f"""Unisons are forbidden.
            There are tolerances in perfect chords progression at root position if:
            - the unison is in a downbeat
            - there is an octave leap
            - if the bass is really high, or the soprano really low
            - note that the unison alto-tenor is really clumsy.
            """,n1,n2,s1.title,s2.title)
Exemplo n.º 27
0
def rule_221(cp, cf):
    """Rule 21 of cp2_note_against_note"""
    for n1, na in tools.iter_melodies(cp,cf,alone=False):
        pn1, pna = [util.to_pitch(n) for n in (n1, na)]
        if not pn1.isImperfectlyConsonantWith(pna):
            warn(f"Prefer imperfect consonances",n1,na,cp.title)
Exemplo n.º 28
0
def rule_6(cp,cf):
    """La dissonance formant note de passage est préférable à celle formant broderie"""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if not n2p.isConsonantWith(nbp) and cp.isCambiata(n2):
            warn(f"A dissonant passing tone is better than a dissonant cambiata",cp.title,n2)
Exemplo n.º 29
0
def rule_12(cp, cf):
    """Il est défendu de donner l'impression de l'accord de quarte et sixte au temps fort. On pourra le faire - avec une grande réserve - au temps faible pour conserver un mouvement mélodique élégant, ou pour sauver des quintes ou des octaves"""
    for n1, n2 in tools.iter_melodies(cp,cf,all=True):
        if n1.pitch.isInterval(6,True):
            warn("Please check that there is no impression of second inversion chord", n1, n2)
Exemplo n.º 30
0
def rule_19(cp, cf):
    """Lorsque deux dissonances se suivent, il faut que la première soit considérée comme broderie. Il est défendu d'avoir deux dissonances formées par deux notes de passage."""
    for (n1, na), (n2, nb) in util.pairwise(tools.iter_melodies(cp,cf,alone=False)):
        n1p, nap, n2p, nbp = [util.to_pitch(x) for x in (n1,na, n2, nb)]
        if not n1p.isConsonantWith(nap) and not n2p.isConsonantWith(nbp) and not cp.isCambiata(n1,upbeat=False):
            warn(f"If there is two dissonant pitches in a row, the first one must be a cambiata",cp.title,n1,na)