def _expandTree(self, parent, lowestDurationLevel, durationLevels,
                    durationSubdivisions, barDuration, currentLevel):

        # return up the stack if we're at the lowest duration level
        if (lowestDurationLevel - currentLevel) < 0:
            return

        parentLevel = currentLevel - 1

        # calculate duration of child
        subdivisionsParent = durationSubdivisions[parentLevel]
        parentDuration = parent.getDuration()
        duration = parentDuration / subdivisionsParent

        # create as many children as the number of subdivisions of the parent
        for _ in range(subdivisionsParent):
            child = RhythmTree(duration, currentLevel)
            parent.addChild(child)

            child.assignMetricalAccent(parent, currentLevel)

            self._expandTree(child, lowestDurationLevel, durationLevels,
                             durationSubdivisions, barDuration,
                             currentLevel + 1)
        return parent
예제 #2
0
def testScoresAreModifiedCorrectlyForDensity():
    d1 = RhythmTree(1, 0)
    d2 = RhythmTree(1, 1)
    d3 = RhythmTree(1, 2)
    candidates = [d1, d2, d3]
    scores = [0.8, 0.6, 0.5]
    r.densityImpact = 1

    expectedScores = [
        0.10000000000000002, 0.13333333333333333, 0.16666666666666666
    ]
    newScores = r._modifyScoresForDensity(candidates, scores, 3)

    assert newScores == expectedScores
예제 #3
0
def testCalcScoreDistHarmonicTactusReturnsCorrectScores():
    d1 = RhythmTree(1, 0)
    d2 = RhythmTree(1, 1)
    d3 = RhythmTree(1, 2)
    d4 = RhythmTree(1, 3)

    candidates = [d1, d2, d3, d4]
    expectedScores = [0.4, 0.6, 1, 0.6]

    r.densityImpact = 0
    r.entropyImpact = 0
    scores = r._calcDistFromTactusMetric(candidates, 2)

    assert scores == expectedScores
예제 #4
0
def testRhythmicSpaceIsCreatedCorrectly():
    m = Metre("3/4", "quarternote")
    rsf = RhythmTreeFactory()
    rs2 = rsf.createRhythmTree(2, m)

    rs = RhythmTree(3, 0,
                    [RhythmTree(1, 1,
                                [RhythmTree(0.5, 2), RhythmTree(0.5, 2)]),
                     RhythmTree(1, 1,
                                [RhythmTree(0.5, 2), RhythmTree(0.5, 2)]),
                     RhythmTree(1, 1,
                                [RhythmTree(0.5, 2), RhythmTree(0.5, 2)])])

    assert str(rs) == str(rs2)
    def _expandNode(self, lowestDurationLevel, currentLevel, parent):

        numSubdivisions = 2

        # return up the stack if we've reached the desired depth
        if (lowestDurationLevel - currentLevel) < 0:
            return
        parentDuration = parent.getDuration()
        duration = parentDuration / numSubdivisions
        for _ in range(2):
            child = RhythmTree(duration, currentLevel)
            parent.addChild(child)

            # assign metrical accent to child
            child.assignMetricalAccent(parent, currentLevel)

            self._expandNode(lowestDurationLevel, currentLevel + 1, child)
    def _createChildren(self, parent, number, noteDuration, durationLevel):
        """Creates a number of children with a note duration and duration
        level

        Args:
            parent (RhythmTree): Node we want to add the children to
            number (int): Number of children to be added
            noteDuration (float): Note duration of children
            durationLevel (float): duration level of children

        Returns:
            parent (RhythmTree)
        """
        parentMetricalAccent = parent.getMetricalAccent()

        # create children, add them to parent and assign them a metrical accent
        for i in range(number):
            child = RhythmTree(noteDuration, durationLevel)

            if i == 0:
                child.setMetricalAccent(parentMetricalAccent)
            else:
                child.setMetricalAccent(durationLevel)

            parent.addChild(child)

        return parent
    def createRhythmTree(self,
                         lowestDurationLevel,
                         metre,
                         highestDurationLevel=0):
        """Instantiate and returns a rhythm space tree

        Args:
            lowestDurationLevel (int): Lowest duration level of the rhythm
                                       space to be created
            metre (Metre): Metre object
        """
        startLevel = highestDurationLevel
        timeSignature = metre.getTimeSignature()
        duration = RhythmTreeFactory.getDurationAtDurationLevel(
            timeSignature, startLevel)

        # instantiate root level of rhythm tree
        rhythmTree = RhythmTree(duration, startLevel)
        rhythmTree.setMetricalAccent(startLevel)
        rhythmTree.setLowestDurationLevel(lowestDurationLevel)

        durationLevels = metre.getDurationLevels()
        durationSubdivisions = metre.getDurationSubdivisions()

        if startLevel == lowestDurationLevel:
            return rhythmTree

        # expand root
        rhythmTree = self._expandTree(rhythmTree, lowestDurationLevel,
                                      durationLevels, durationSubdivisions,
                                      duration, startLevel + 1)
        return rhythmTree
    def _insertTriplet(self, parent):

        # add extra child to parent
        parentDurationLevel = parent.getDurationLevel()
        child = RhythmTree(1, parentDurationLevel + 1)
        child.setMetricalAccent(parentDurationLevel + 1)

        parent.addChild(child)

        tripletItems = parent.getChildren()

        tripletItemDuration = parent.calculateTupletItemDuration(3)

        # change duration of children
        for item in tripletItems:
            item.setDuration(tripletItemDuration)

        lowestDurationLevel = parent.getLowestDurationLevel()
        startLevel = parentDurationLevel + 2

        # expand triplet
        self._modifyTripletItemsDurations(parent, parentDurationLevel)
        self._expandNode(lowestDurationLevel, startLevel, parent.children[2])
예제 #9
0
def testInsertTriplet():
    rsf = RhythmTreeFactory()
    m = Metre("4/4", "quarternote")

    rs = rsf.createRhythmTree(3, m)

    rs1 = RhythmTree(2, 0,
                     [RhythmTree(1, 1,
                                 [RhythmTree(0.5, 2), RhythmTree(0.5, 2)]),
                      RhythmTree(1, 1,
                                 [RhythmTree(0.5, 2), RhythmTree(0.5, 2)])])

    rsf._insertTriplet(rs.children[0])
    assert len(rs.children[0].children) == 3
    for child in rs.children[0].children:
        assert 0.66 < child.duration < 0.67
예제 #10
0
def testRhythmicSpaceIsInstantiatedCorrectly():
    root = RhythmTree(1, 2)
    assert root.duration == 1
    assert root.durationLevel == 2
def testChordProgressionsAreGeneratedCorrectly():
    hpg = HarmonyPitchGenerator()
    rs1 = RhythmTree(3.5, 0)
    rs2 = RhythmTree(0.5, 0)
    rs3 = RhythmTree(2, 0)
    rs4 = RhythmTree(2, 1)

    rs1.setMetricalAccent(0)
    rs2.setMetricalAccent(2)
    rs3.setMetricalAccent(0)
    rs4.setMetricalAccent(1)

    harmonicRhythm = [rs1, rs2, rs3, rs4]
    progression = hpg.generateHarmonyPitchMU(harmonicRhythm, 0.7, 0.7,
                                             "musicunit")
    print([x.pitchSet for x in progression])
def testChordProgressionsForCadencesAreCreatedCorrectly():
    rs1 = RhythmTree(4, 1)
    rs2 = RhythmTree(3, 1)
    rs3 = RhythmTree(2, 1)

    rs1.setMetricalAccent(1)
    rs2.setMetricalAccent(2)
    rs3.setMetricalAccent(3)

    hpg = HarmonyPitchGenerator()
    cadence = hpg._createCadence([rs1, rs2, rs3])
    assert len(cadence) == 2
def testBackboneNotesAreGeneratedCorrectly():
    c1 = Chord("0+-")
    r1 = RhythmTree(1, 1)
    r1.metricalAccent = 0
    n1 = Note(r1, c1)

    c2 = Chord("5-+")
    r2 = RhythmTree(1, 1)
    r2.metricalAccent = 2
    n2 = Note(r2, c2)

    c3 = Chord("7+--")
    r3 = RhythmTree(1, 1)
    r3.metricalAccent = 1
    n3 = Note(r3, c3)

    c4 = Chord("0-+")
    r4 = RhythmTree(1, 1)
    r4.metricalAccent = 0
    n4 = Note(r4, c4)

    backboneNotes = [n1, n2, n3, n4]

    notes = mbg.generateBackbonePitches(backboneNotes,
                                        pitchHeight=-0.5,
                                        pitchRange=0,
                                        melodicComplexity=0)

    assert len(notes) == 4
    s = mbg._realizeM21Sequence(notes)