Mercurial > hg > syncopation-dataset
diff Syncopation models/synpy/WNBD.py @ 45:6e9154fc58df
moving the code files to the synpy package directory
author | christopherh <christopher.harte@eecs.qmul.ac.uk> |
---|---|
date | Thu, 23 Apr 2015 23:52:04 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Syncopation models/synpy/WNBD.py Thu Apr 23 23:52:04 2015 +0100 @@ -0,0 +1,128 @@ +''' +Author: Chunyang Song +Institution: Centre for Digital Music, Queen Mary University of London + +''' +from basic_functions import repeat, get_note_indices + +# To find the product of multiple numbers +def cumu_multiply(numbers): + product = 1 + for n in numbers: + product = product*n + return product + +def get_syncopation(bar, parameters = None): + syncopation = None + + noteSequence = bar.get_note_sequence() + barTicks = bar.get_bar_ticks() + subdivisionSequence = bar.get_subdivision_sequence() + strongBeatLevel = bar.get_beat_level() + + nextbarNoteSequence = None + if bar.get_next_bar() != None: + nextbarNoteSequence = bar.get_next_bar().get_note_sequence() + + # calculate each strong beat ticks + numberOfBeats = cumu_multiply(subdivisionSequence[:strongBeatLevel+1]) + beatIntervalTicks = barTicks/numberOfBeats + # beatsTicks represents the ticks for all the beats in the current bar and the first two beats in the next bar + beatsTicks = [i*beatIntervalTicks for i in range(numberOfBeats+2)] + #print beatsTicks + totalSyncopation = 0 + for note in noteSequence: + # print note.to_string() + # find such beatIndex such that note.startTime is located between (including) beatsTicks[beatIndex] and (not including) beatsTicks[beatIndex+1] + beatIndex = 0 + while note.startTime < beatsTicks[beatIndex] or note.startTime >= beatsTicks[beatIndex+1]: + beatIndex += 1 + + # print beatIndex + # calculate the distance of this note to its nearest beat + distanceToBeatOnLeft = abs(note.startTime - beatsTicks[beatIndex])/float(beatIntervalTicks) + distanceToBeatOnRight = abs(note.startTime - beatsTicks[beatIndex+1])/float(beatIntervalTicks) + distanceToNearestBeat = min(distanceToBeatOnLeft,distanceToBeatOnRight) + # print distanceToNearestBeat + + # calculate the WNBD measure for this note, and add to total syncopation value for this bar + if distanceToNearestBeat == 0: + totalSyncopation += 0 + # or if this note is held on past the following beat, but ends on or before the later beat + elif beatsTicks[beatIndex+1] < note.startTime+note.duration <= beatsTicks[beatIndex+2]: + totalSyncopation += float(2)/distanceToNearestBeat + else: + totalSyncopation += float(1)/distanceToNearestBeat + # print totalSyncopation + + return totalSyncopation + +#def get_syncopation(seq, subdivision_seq, strong_beat_level, postbar_seq): +# def get_syncopation(bar, parameters = None): +# syncopation = None + +# binarySequence = bar.get_binary_sequence() +# sequenceLength = len(binarySequence) +# subdivisionSequence = bar.get_subdivision_sequence() +# strongBeatLevel = bar.get_beat_level() +# nextbarBinarySequence = None + +# if bar.get_next_bar() != None: +# nextbarBinarySequence = bar.get_next_bar().get_binary_sequence() + +# numberOfBeats = cumu_multiply(subdivisionSequence[0:strongBeatLevel+1]) # numberOfBeats is the number of strong beats + +# if sequenceLength % numberOfBeats != 0: +# print 'Error: the length of sequence is not subdivable by the subdivision factor in subdivision sequence.' +# else: +# # Find the indices of all the strong-beats +# beatIndices = [] +# beatInterval = sequenceLength / numberOfBeats +# for i in range(numberOfBeats+1): +# beatIndices.append(i*beatInterval) +# if nextbarBinarySequence != None: # if there is a postbar_seq, add another two beats index for later calculation +# beatIndices += [sequenceLength+beatInterval, sequenceLength+ 2* beatInterval] + +# noteIndices = get_note_indices(binarySequence) # all the notes + +# # Calculate the WNBD measure for each note +# def measure_pernote(noteIndices, nextNoteIndex): +# # Find the nearest beats where this note locates - in [beat_indices[j], beat_indices[j+1]) +# j = 0 +# while noteIndices < beatIndices[j] or noteIndices >= beatIndices[j+1]: +# j = j + 1 + +# # The distance of note to nearest beat normalised by the beat interval +# distanceToNearestBeat = min(abs(noteIndices - beatIndices[j]), abs(noteIndices - beatIndices[j+1]))/float(beatInterval) + +# # if this note is on-beat +# if distanceToNearestBeat == 0: +# measure = 0 +# # or if this note is held on past the following beat, but ends on or before the later beat +# elif beatIndices[j+1] < nextNoteIndex <= beatIndices[j+2]: +# measure = float(2)/distanceToNearestBeat +# else: +# measure = float(1)/distanceToNearestBeat +# return measure + +# total = 0 +# for i in range(len(noteIndices)): +# # if this is the last note, end_time is the index of the following note in the next bar +# if i == len(noteIndices)-1: +# # if the next bar is not none or a bar of full rest, +# # the nextNoteIndex is the sum of sequence length in the current bar and the noteIndex in the next bar +# if nextbarBinarySequence != None and nextbarBinarySequence != repeat([0],len(nextbarBinarySequence)): +# nextNoteIndex = get_note_indices(nextbarBinarySequence)[0]+sequenceLength +# # else when the next bar is none or full rest, end_time is the end of this sequence. +# else: +# nextNoteIndex = sequenceLength +# # else this is not the last note, the nextNoteIndex is the following element in the noteIndices list +# else: +# nextNoteIndex = noteIndices[i+1] +# # sum up the syncopation value for individual note at noteIndices[i] +# total += measure_pernote(noteIndices[i],nextNoteIndex) + +# #syncopation = float(total) / len(note_indices) + +# # return the total value, leave the normalisation done in the end +# return total