Mercurial > hg > syncopation-dataset
view Syncopation models/WNBD.py @ 20:b959c2acb927
Refactored all models except for KTH, all past testing except for SG.
author | csong <csong@eecs.qmul.ac.uk> |
---|---|
date | Tue, 07 Apr 2015 19:05:07 +0100 |
parents | 031e2ccb1fb6 |
children | df1e7c378ee0 |
line wrap: on
line source
''' 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(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