예제 #1
0
def vanDerWeijPerform(score, segments, expression_vectors):
    deviations = Deviations()
    tempo_deviations = {}

    for segment, expression in zip(segments, expression_vectors):
        start_tempo = expression[3]
        tempo_direction = expression[5]
        start_loudness = expression[4]
        loudness_direction = expression[6]
        articulation = expression[2]
        i = 0
        beat = 0

        for note in segment:
            velocity = start_loudness + i * loudness_direction

            i += 1


    score.tempo = tempo
    performance = NoteList()
    time = 0
    for i in range(len(score)):
        on = time + structure.ioi(score, i) * math.exp(expression[i][0])
        loudness = average_loudness * math.exp(expression[i][1])
        off = on + structure.duration(score, i) * math.exp(expression[i][3])
        performance.insert(Note(int(on), int(off), score[i].pitch, int(loudness), 0))
        time = on
    return performance
def expressionWidmer(alignment):
    performance = alignment.expressiveMelody()
    melodyscore = alignment.melody()
    score = tools.parseScore(melodyscore)
    # The two above should be guaranteed to be of equal length.
    # However, better be safe than sorry
    if len(performance) != len(score):
        print('This shouldn\'t happen: melodyscore and performance lengths don\'t match: {0} and {1}'.format(len(score), len(performance)))
    else:
        print("This is good, performance length and score length match")

    # Mean loudness
    mean_l = 0.0
    for note in performance:
        mean_l += note.onvelocity

    mean_l = mean_l / float(len(performance))

    expression = []
    lasttempo = float(alignment.deviations.bpm)
    lastdynamics = mean_l

    # Assume same note order in score and performance (am I being naive?)
    for i in range(len(performance)):
        ioi_ratio = math.log(structure.ioi(performance, i) / float(structure.ioi(score, i)))
        loudness_ratio = math.log(performance[i].onvelocity / mean_l)

        # This obviously results in zero divisions
        #articulation = math.log(structure.silence(performance, i) / float(structure.silence(score, i)))
        articulation = 0

        if(structure.duration(performance, i) < 1):
            print("Invalid performance note :( skipping")
            continue
        duration_ratio = math.log(structure.duration(performance, i) / float(structure.duration(score, i)))

        # To be implemented: second order ioi loudness and articulation
        ioi_change = 0
        loudness_change = 0
        articulation_change = 0

        # E = (ioi_r, loudness_r, articulation, duration_r, ioi_ch, loundess_ch)
        e = (ioi_ratio, loudness_ratio, articulation, duration_ratio, ioi_change, loudness_change)
        expression.append(e)


    return expression
예제 #3
0
def widmerPerform(score, expression, average_loudness=80, tempo=80):
    score.tempo = tempo
    performance = NoteList()
    time = 0
    for i in range(len(score)):
        on = time + structure.ioi(score, i) * math.exp(expression[i][0])
        loudness = average_loudness * math.exp(expression[i][1])
        off = on + structure.duration(score, i) * math.exp(expression[i][3])
        performance.insert(Note(int(on), int(off), score[i].pitch, int(loudness), 0))
        time = on
    return performance
def vanDerWeijExpression(alignment, segments):
    performance = alignment.expressiveMelody()
    scorenotes = []
    average_loudness = 0
    for s in segments:
        for n in s:
            scorenotes.append(n)
            average_loudness += n.onvelocity
    average_loudness /= float(len(scorenotes))
    # The two above should be guaranteed to be of equal length.
    # However, better be safe than sorry
    if len(performance) != sum([len(x) for x in segments]):
        print('WARNING: Melodyscore and performance are different (should not happen): {0} and {1}'.format(len(sum([len(x) for x in segments])), len(performance)))

    expression = []
    # Counter for position in notelists performance and scorenotes
    i = 0
    for segment in segments:
        length = float(len(segment))
        average_articulation = 0.0
        average_ioi_ratio = 0.0
        loudnesses = []
        for note in segment:
            pointer = note.annotation
            scorepart = alignment.melody()[pointer[0]]
            scoremeasure = scorepart[pointer[1]]
            scorevoice = scoremeasure[pointer[2]]
            scorenote = scorevoice[pointer[3]]
            measure = scoremeasure.number


            # Find out if the next note is a rest, if so use the ratio between expressive duration and duration
            useScoreDuration = False
            # Last note of this measure?
            if pointer[3] + 1 == len(scorevoice):
                # Last measure?
                if pointer[1] + 1 >= len(scorepart):
                    useScoreDuration = True
                # Don't know what to do if the voice in the next measure contains no notes
                elif scorepart[pointer[1]+1].getElementById(scorevoice.id) == None:
                    measure = scorepart[pointer[1]+1]
                    useScoreDuration = True
                elif len(scorepart[pointer[1]+1].getElementById(scorevoice.id).notes) == 0:
                    measure = scorepart[pointer[1]+1]
                    useScoreDuration = True
                # First note of this voice in the next measure is a rest?
                elif scorepart[pointer[1]+1].getElementById(scorevoice.id).notes[0].isRest:
                    measure = scorepart[pointer[1]+1]
                    useScoreDuration = True
            elif scorevoice[pointer[3]+1].isRest:
                useScoreDuration = True

            ioi = 1
            if useScoreDuration or i+1 == len(performance):
                ioi = performance.microseconds_to_ticks(alignment.deviations.getExpressiveDuration(scoremeasure.number, scorenote.offset, scorenote.duration.quarterLength))
            else:
                ioi = structure.ioi(performance, i+1)
                # Ugly hack to fix something
                if ioi == 0:
                    ioi = performance.microseconds_to_ticks(
                        alignment.deviations.getExpressiveDuration(scoremeasure.number, scorenote.offset, scorenote.duration.quarterLength)
                    )

            #print "Performance ioi: {0}, score + tempo ioi: {1}, performance duration: {2}, measure{3}, offset {4}".format(ioi,\
            #    performance.microseconds_to_ticks(alignment.deviations.getExpressiveDuration(scoremeasure.number, scorenote.offset,\
            #    scorenote.duration.quarterLength)), structure.duration(performance, i), scoremeasure.number, scorenote.offset)

            # Results in zero division error in Mozart: 28 (not needed anyway so let's kick it out)
            #average_ioi_ratio += math.log(structure.ioi(performance, i) / float(structure.ioi(scorenotes, i)))
            average_ioi_ratio += 0
            average_articulation += structure.duration(performance, i) / float(ioi)
            loudnesses.append(performance[i].onvelocity)
            i += 1

        tempos = []
        r = list(range(segment[0].annotation[1], segment[int(length)-1].annotation[1]+1))
        for m in r:
            pointer = note.annotation
            scoremeasure = alignment.melody()[pointer[0]][pointer[1]]
            measure = scoremeasure.number
            #print scoremeasure.duration.quarterLength
            lasttempo = 1.0
            for b in range(int(scoremeasure.barDuration.quarterLength)):
                if (scoremeasure.number, b) in alignment.deviations.tempo_deviations:
                    lasttempo = alignment.deviations.tempo_deviations[scoremeasure.number, b]
                    tempos.append(lasttempo)
                else:
                    tempos.append(lasttempo)


        # Calculate performance parameters/features
        average_ioi_ratio /= length
        average_articulation /= length
        average_tempo = sum(tempos) / float(len(tempos))
        #average_relative_loudness = math.log((sum(loudnesses) / length) / average_loudness)
        average_relative_loudness = (sum(loudnesses) / length) / float(average_loudness)
        if len(segment) == 1:
            (start_loudness, loudness_direction) = (average_loudness, 0)
            (start_tempo, tempo_direction) = (tempos[0], 0)
        else:
            note_onsets = [n.on for n in segment]
            (start_loudness, loudness_direction) = (0, 0) #linear_fit(note_onsets, loudnesses)
            (start_tempo, tempo_direction) = (0, 0) #linear_fit(range(len(tempos)), tempos)

        expression.append((average_ioi_ratio, average_relative_loudness, average_articulation, average_tempo, start_tempo, start_loudness, tempo_direction, loudness_direction))

    return expression