Пример #1
0
def _Rule_10(s: stave.Stave):
    """Éviter les marches d'harmonie"""
    for start in range(s.barNumber):
        for end in range(start, s.barNumber):

            motif = []
            for i in range(start, end + 1):
                for n in s.getBar(i):
                    motif.append(n)

            motif_bar_number = end - start + 1
            try:
                following = []
                for i in range(end + 1, motif_bar_number + end + 1):
                    for n in s.getBar(i):
                        following.append(n)
            except IndexError:
                break
            try:
                if tools.matchSequence(motif, following, s.scale):
                    msg = f"Sequence in {s.title}. It should be avoided"
                    if len(motif) == 1:
                        continue
                    if len(motif) <= 2:
                        error.warn(msg, motif, following)
                    else:
                        raise error.CompositionError(msg, motif, following)
            except ValueError:
                # It should be that the relative one is encountered, so no sequence here
                continue
Пример #2
0
def rule_4(s: stave.Stave):
    """On doit commencer par une consonance parfaite (unisson, quinte ou douzième, octave ou quinzième) et finir par l'octave ou l'unisson
    """
    def nb_error(poss, posi, notes):
        if len(notes) != 2:
            raise error.CompositionError(
                f"Two notes are expected at the {poss} of the track",
                s.getBar(posi))

    # start
    notes = s.atFirstPos(0)
    nb_error("start", 0, notes)

    if not notes[0].pitch.isPerfectlyConsonantWith(notes[1].pitch):
        raise error.CompositionError(
            "The first two notes are not fully consonant.", s.getBar(0))

    # end
    notes = s.atFirstPos(s.lastFirstPos)
    nb_error("end", s.getBar(s.barNumber - 1), notes)

    if not notes[0].pitch.isInterval(1, 8, True).With(notes[1].pitch):
        raise error.CompositionError(
            "The last interval must be an unison or an octave.",
            s.getBar(s.barNumber - 1))
Пример #3
0
def rule_11(cp: stave.Stave, cd: stave.Stave):
    """Les croisements sont tolérés, employés avec une grande réserve"""
    cp_high_part = None

    for cp_n, cd_n in zip(cp.barIter(), cd.barIter()):

        if not (len(cp_n) == len(cd_n) == 1):
            raise error.CompositionError("Two notes are expected", cp_n, cd_n)

        cdn, cpn = cd_n[0], cp_n[0]

        if cp_high_part is None:
            cp_high_part = cpn.pitch.value.semitone > cdn.pitch.value.semitone if cpn.pitch.value.semitone != cdn.pitch.value.semitone else None
        else:
            if cp_high_part is True:
                if cdn.pitch.value.semitone > cpn.pitch.value.semitone:
                    error.warn(
                        "The melodies intersect: cantus firmus is now over the counterpoint",
                        cp_n, cd_n)
                    cp_high_part = False
            elif cp_high_part is False:
                if cpn.pitch.value.semitone > cdn.pitch.value.semitone:
                    error.warn(
                        "The melodies intersect: counterpoint is now over cantus firmus",
                        cp_n, cd_n)
                    cp_high_part = True

            else:
                assert cp_high_part is not None
Пример #4
0
def rule_23(s: stave.Stave):
    """La première et la dernière mesure sont obligatoirement harmonisées par l'accord de tonique à l'état fondamental"""
    c = chord.Chord(1, s.scale)
    for bar in (s.getBar(0), s.getBar(-1)):
        if not c.isInversion([*bar], 0):
            raise error.CompositionError(
                "First and last bar must be at the root position of the chord of the first degree",
                bar)
Пример #5
0
def rule_15(s: stave.Stave):
    """Le contrepoint ne doit pas parcourir une étendue plus grande que la dixième et par exception la onzième."""
    res = tools.min_max(s)
    min = res.min
    max = res.max

    if max.intervalWith(min) == 11:
        error.warn("The counterpoint can exceed the 11th by tolerance only.",
                   *s.barIter())
    if max.intervalWith(min) > 11:
        raise error.CompositionError(
            "It is strictly forbidden to exceed the 11th.", *s.barIter())
Пример #6
0
def rule_26(s: stave.Stave):
    """La première et la dernière mesure sont obligatoirement harmonisées par l'accord de tonique à l'état fondamental"""
    tonic = chord.Chord(1, s.scale)
    for measure in (s.getBar(0), s.getBar(-1)):
        is_error = False
        try:
            if not tonic.isInversion([*measure], 0):
                is_error = True
        except ValueError:
            is_error = True

        if is_error:
            raise error.CompositionError(
                f"In {s.title}, the first bar or the last bar is not the tonic chord at root position",
                measure)
Пример #7
0
def rule_13(s: stave.Stave):
    """Lorsque la dominante du ton se trouve à la partie inférieure - et qu'elle a été précédée de l'accord du premier degré - il faut éviter de la combiner avec une sixte car cela donnerait le sentiment d'un accord de quarte et sixte, ce qui est défendu. Si elle permet de sous-entendre un autre accord, on peut l'employer"""
    """There is maybe a problem here: if the main scale is major, every switch to the relative minor will install it as the main scale and the program will never consider that the swith is finished since not pitch of the major is outside of the minor. Maybe we should consider that we return to the major scale each measure.
    WARNING"""
    current_scale = s.scale
    previous_chord = None

    for bar in s.barIter():
        # change scale if necessary
        if bar[0].pitch not in current_scale or bar[
                1].pitch not in current_scale:
            current_scale = current_scale.relative(scale.Mode.m_full)

        notes = [scalenote.NoteScale(current_scale, n) for n in bar]
        n1, n2 = notes
        # generate chord
        first = chord.Chord(1, current_scale)
        # is it the first degree chord?
        if notes in first:
            previous_chord = notes
            continue
        if previous_chord is not None:
            # is it the dominant in the bass and an interval of sixth?
            low, high = (n1, n2) if n1 < n2 else (n2, n1)
            if low.isDominant and low.note.isInterval(6).With(high.note):
                raise error.CompositionError(
                    "It is forbidden to use a tonic chord followed by a dominant at the bass and a sixth with the dominant",
                    previous_chord, bar)

            # clean-up
            previous_chord = None
Пример #8
0
def rule_16(s: stave.Stave):
    """Le mouvement conjoint est celui qui convient le mieux au style du Contrepoint rigoureux. Employer le mouvement disjoint très discrètement."""
    previous = None
    for bar in s.barIter():
        if previous is not None and bar[0].pitch.intervalWith(
                previous[0].pitch) > 2:
            error.warn("It is better to avoid disjunct motion", previous, bar)
        previous = bar
Пример #9
0
def rule_7(s: stave.Stave):
    """Les intervalles formant consonance parfaites ou imparfaites avec le chant donné sont seuls employés"""
    for bar in s.barIter():
        if len(bar) != 2:
            raise error.CompositionError("Two notes expected", bar)
        ft, sd = bar[0].pitch, bar[1].pitch
        if not ft.isConsonantWith(sd):
            raise error.CompositionError("The notes must be consonant", bar)
Пример #10
0
def rule_6(s: stave.Stave):
    """Le mouvement chromatique est défendu"""
    previous = None
    for elt in s.barIter():
        note = elt[0]
        if previous is not None and previous[
                0].pitch.isChromaticInflectionWith(note.pitch):
            raise error.CompositionError("Chromatic inflection is forbidden",
                                         previous, elt)
        previous = elt
Пример #11
0
def rule_17(s: stave.Stave):
    """Les mouvements de quarte augmentée (triton), quinte dimininuée, de septième majeure et mineure sont défendus"""
    previous = None
    for bar in s.barIter():
        if previous is not None and bar[0].pitch.isQualifiedInterval(
            (5, "diminished"), (4, "augmented"), (7, "minor"),
            (7, "major")).With(previous[0].pitch):
            raise error.CompositionError(
                "Melodic motion can't be a 4th augmented, 5th diminished, 7th minor or major",
                previous, bar)
        previous = bar
Пример #12
0
def rule_12(s: stave.Stave):
    """On ne doit moduler qu'aux tons relatifs"""
    sc = scale.Scale(s.keynote, s.mode)
    relative = sc.relative(scale.Mode.m_full)
    for bar in s.barIter():
        note = bar[0]
        if note.pitch not in sc:
            if note.pitch not in relative:
                raise error.CompositionError(
                    "It is forbidden to modulate outside the relative key",
                    bar)
Пример #13
0
def rule_21(s: stave.Stave, ratio=5 / 20):
    """Employer de préférence les consonances imparfaites"""
    bars = []
    for bar in s.barIter():
        ft, sd = [util.to_pitch(n) for n in bar]
        if ft.isPerfectlyConsonantWith(sd):
            bars.append(bar)

    if len(bars) / len(s) > ratio:
        error.warn(
            "The number of perfect consonances is possibly higher than requested",
            *bars)
Пример #14
0
def rule_14(s: stave.Stave):
    """Pour la fausse relation de triton, la règle est la même qu'en harmonie : la fausse relation de triton est défendue."""
    get_pitches = lambda b: sorted([util.to_pitch(x) for x in b],
                                   key=lambda x: x.value.semitone)

    old_high = None
    for i, bar in enumerate(s.barIter()):
        if len(bar) != 2:
            raise error.CompositionError("Two notes expected", bar)

        bass, high = get_pitches(bar)

        # check with last bar
        if old_high is not None and bass.isQualifiedInterval(
            (4, 'augmented')).With(old_high):
            raise error.CompositionError("False relation is forbidden", bar)
        # check with next bar
        if i + 1 < s.barNumber:
            next_bass, next_high = get_pitches(s.getBar(i + 1))
            if bass.isQualifiedInterval((4, 'augmented')).With(next_high):
                raise error.CompositionError("False relation is forbidden",
                                             bar)
        # prepare next iteration
        old_high = high
Пример #15
0
def rule_1(s: stave.Stave):
    """
    s is the main stave
    1 - Le contrepoint se compose d'une partie en rondes combinée avec le Chant donné (en rondes)

    """
    for nb, bar in enumerate(s.barIter()):

        # check that each bar contains only two notes
        if len(bar.elts) != 2:
            raise error.CompositionError("Number of breve should be two", bar)

        # check that each note is a breve
        if bar.elts[0].duration != bar.elts[1].duration and bar.elts[
                0].duration != note.Duration.SEMIBREVE:
            raise error.CompositionError("The notes are not breves", bar)
Пример #16
0
def rule_5(s: stave.Stave):
    """L'unisson est défendu dans le courant du contrepoint"""

    for elt in s.barIter():

        #if elt.pos == 0 or elt.pos == s.lastFirstPos:
        if elt.pos in (0, s.barNumber - 1):
            # first and last interval can be unisons.
            continue

        if len(elt) != 2:
            raise error.CompositionError("Two notes are expected.", elt)

        if elt[0].pitch == elt[1].pitch:
            raise error.CompositionError(
                "Unison is forbidden inside the couterpoint", elt)
Пример #17
0
def rule_9(s: stave.Stave):
    """Les notes ne peuvent pas êtres répétées plus d'une fois - on ne peut les faire entendre plus de deux fois de suite."""
    nb = 0
    previous = None
    for elt in s.barIter():
        if elt.pos != 0 and elt[0].pitch == previous.pitch:
            nb += 1
        else:
            nb = 0

        if nb >= 2:
            raise error.CompositionError(
                "It is forbidden to use the same note more than two times in a row",
                elt)

        previous = elt[0]
Пример #18
0
def no_consecutive(interval: int, s1: stave.Stave, s2: stave.Stave) -> bool:
    """Raise error if two interval in a row
    between s1 and s2"""
    nb = 0
    for n1, n2 in zip(s1, s2):
        p1, p2 = [util.to_pitch(n) for n in (n1, n2)]
        if p1.isInterval(interval, True).With(p2):
            nb += 1
        else:
            nb = 0

        if nb >= 2:
            raise error.CompositionError(
                f"It is forbidden to have two {interval} in a row", n1, n2,
                s1.findBarOf(n1))

    return True
Пример #19
0
def no_more_than(s: stave.Stave, x: int) -> bool:
    """s is a pure melody. 
    Warn if one note is used more
    than x times in a row
    """
    nb = 0
    previous = None
    for i, n in enumerate(s.notes):
        pn = util.to_pitch(n)
        if i != 0 and pn == previous:
            nb += 1
        else:
            nb = 0
        if nb >= x:
            error.warn(
                f"It is forbidden to use the same note more than {x} times if a row",
                n, s.findBarOf(n))
        previous = pn
Пример #20
0
def no_more_than(s: stave.Stave, x: int) -> bool:
    """s is a pure melody. Return True if no problem.
    Raise CompositionError if one note is used more
    than x times in a row
    """
    nb = 0
    previous = None
    for i, n in enumerate(s.notes):
        pn = util.to_pitch(n)
        if i != 0 and pn == previous:
            nb += 1
        else:
            nb = 0
        if nb >= x:
            raise error.CompositionError(
                f"It is forbidden to use the same note more than {x} times if a row",
                n, s.findBarOf(n))
        previous = pn

    return True
Пример #21
0
def rule_8(s: stave.Stave):
    """On ne doit pas entendre plus de trois tierces ou trois sixtes de suite"""
    _6 = _3 = 0

    for bar in s.barIter():
        if len(bar) != 2:
            raise error.CompositionError("Two notes expected", bar)
        f, s = bar[0].pitch, bar[1].pitch
        int_ = f.intervalWith(s, True)
        if int_ == 3:
            _3 += 1
            _6 = 0
        elif int_ == 6:
            _6 += 1
            _3 = 0
        else:
            _6 = _3 = 0

        if 4 in (_6, _3):
            raise error.CompositionError(
                "It is forbidden to use more than three sixths or thirds in a row",
                bar)
Пример #22
0
def rule_18(s: stave.Stave):
    """Comme pour l'harmonie, le mouvement contraire est préférable à l'oblique, et ce dernier au direct"""
    movs = {
        motion.MotionType.direct: 0,
        motion.MotionType.contrary: 0,
        motion.MotionType.oblique: 0
    }
    previous_bar = None

    for bar in s.barIter():
        notes = [*bar]
        notes.sort(key=lambda x: x.pitch.value.semitone)
        if previous_bar is not None:
            movs[motion.MotionType.motion(*previous_bar, *notes)] += 1
        previous_bar = [*notes]

    error.warn(
        f"Number of contrary movements: {movs[motion.MotionType.contrary]}; oblique movements: {movs[motion.MotionType.oblique]}; direct movements: {movs[motion.MotionType.direct]}. "
    )
    error.warn(
        "Prefer the contrary movement to the oblique, and the oblique to the direct. "
    )
Пример #23
0
def rule_22(cp: stave.Stave, cf: stave.Stave):
    """À l'avant dernière mesure, on emploiera la sixte majeure lorsque le chant donné sera à la basse et la tierce mineure suivie de l'octave ou de l'unisson lorsqu'il sera à la partie supérieure"""
    # is the cantus firmus above or beyond?
    cp_above = None
    for cpn, cfn in zip(cp.barIter(), cf.barIter()):
        cpn, cfn = [util.to_pitch(n[0]) for n in (cpn, cfn)]
        if cpn != cfn:
            cp_above = cpn.value.step > cfn.value.step
            break
    assert cp_above is not None

    # check the before last one bar
    cpn = util.to_pitch(cp.getBar(cp.barNumber - 2)[0])
    cfn = util.to_pitch(cf.getBar(cf.barNumber - 2)[0])
    cp = cp.copy()
    cp.extend(cf)
    before_last_bar = cp.getBar(cp.barNumber - 2)

    if cp_above and not cfn.isQualifiedInterval((6, "major")):
        raise error.CompositionError(
            "The before last interval must be a 6th major", before_last_bar)
    elif not cp_above and not cfn.isQualifiedInterval((3, "minor")):
        raise error.CompositionError(
            "The before last interval must be a 3rd minor", before_last_bar)
Пример #24
0
def rule_19(s: stave.Stave):
    """Ne jamais arriver sur une quinte ou une octave par mouvement direct. A priori, deux quintes ou deux octaves sont défendues."""
    # 2 5th/8ve in a row
    previous = None
    for bar in s.barIter():
        interval = bar[0].pitch.intervalWith(bar[1].pitch, True)
        if previous is not None and interval in (8, 5):
            if interval == previous:
                raise error.CompositionError(
                    "Two 5th or two 8ve in a row is forbidden", previous_bar,
                    bar)
            # direct motion?
            previous_notes = [*previous_bar]
            notes = [*bar]
            previous_notes.sort(key=_semitone)
            notes.sort(key=_semitone)
            if motion.MotionType.motion(*previous_notes,
                                        *notes) == motion.MotionType.direct:
                raise error.CompositionError(
                    "It is forbidden to go to a 5th or an 8ve by direct motion",
                    previous, bar)

        previous_bar = bar
        previous = interval
Пример #25
0
imgList = []
with open(inputFile) as csvfile:
    reader = csv.reader(csvfile, quoting=csv.QUOTE_NONNUMERIC)
    for row in reader:
        imgList.append(row)
image = np.array(imgList)

if args.L_flip:
    image = np.flip(image, axis=1)

if args.J_flip:
    image = np.flip(image, axis=0)
    image = np.flip(image, axis=1)

#creating the staves + loading the parameters from the config file
staveTop = Stave(image, configFile)
if not (args.one_face):
    staveBottom = Stave(image, configFile)

#scale up the images with linear extrapolation to get better results for small regions
staveTop.ScaleImage(10)
if not (args.one_face):
    staveBottom.ScaleImage(10)

#get the scaled image; it's used later for showing the regions for debugging
img_edges = staveTop.getImage()

#finding the staves - triggers an algorithm that looks for the stave, using relative coordinates
if args.one_face:
    staveTop.FindStaveWithin(0, 1.0, 0, 1.0)
else:
Пример #26
0
def correctRatioStave():
    global_image = 18 * np.ones([1240, 3160])
    region_image = 30 * np.ones([251, 3000])
    global_image[400:651, 80:3080] = region_image
    mystave = Stave(global_image, "parameters/param-for-testing.cfg")
    return mystave