annotate 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
rev   line source
csong@0 1 '''
csong@0 2 Author: Chunyang Song
csong@0 3 Institution: Centre for Digital Music, Queen Mary University of London
csong@0 4
csong@1 5 '''
csong@20 6 from basic_functions import repeat, get_note_indices
csong@0 7
csong@2 8 # To find the product of multiple numbers
csong@1 9 def cumu_multiply(numbers):
csong@1 10 product = 1
csong@1 11 for n in numbers:
csong@1 12 product = product*n
csong@1 13 return product
csong@0 14
csong@20 15 #def get_syncopation(seq, subdivision_seq, strong_beat_level, postbar_seq):
csong@20 16 def get_syncopation(bar, parameters = None):
csong@1 17 syncopation = None
csong@1 18
csong@20 19 binarySequence = bar.get_binary_sequence()
csong@20 20 sequenceLength = len(binarySequence)
csong@20 21 subdivisionSequence = bar.get_subdivision_sequence()
csong@20 22 strongBeatLevel = bar.get_beat_level()
csong@20 23 nextbarBinarySequence = None
csong@20 24
csong@20 25 if bar.get_next_bar() != None:
csong@20 26 nextbarBinarySequence = bar.get_next_bar().get_binary_sequence()
csong@20 27
csong@20 28 numberOfBeats = cumu_multiply(subdivisionSequence[0:strongBeatLevel+1]) # numberOfBeats is the number of strong beats
csong@2 29
csong@20 30 if sequenceLength % numberOfBeats != 0:
csong@20 31 print 'Error: the length of sequence is not subdivable by the subdivision factor in subdivision sequence.'
csong@1 32 else:
csong@1 33 # Find the indices of all the strong-beats
csong@20 34 beatIndices = []
csong@20 35 beatInterval = sequenceLength / numberOfBeats
csong@20 36 for i in range(numberOfBeats+1):
csong@20 37 beatIndices.append(i*beatInterval)
csong@20 38 if nextbarBinarySequence != None: # if there is a postbar_seq, add another two beats index for later calculation
csong@20 39 beatIndices += [sequenceLength+beatInterval, sequenceLength+ 2* beatInterval]
csong@0 40
csong@20 41 noteIndices = get_note_indices(binarySequence) # all the notes
csong@0 42
csong@1 43 # Calculate the WNBD measure for each note
csong@20 44 def measure_pernote(noteIndices, nextNoteIndex):
csong@1 45 # Find the nearest beats where this note locates - in [beat_indices[j], beat_indices[j+1])
csong@1 46 j = 0
csong@20 47 while noteIndices < beatIndices[j] or noteIndices >= beatIndices[j+1]:
csong@1 48 j = j + 1
csong@1 49
csong@1 50 # The distance of note to nearest beat normalised by the beat interval
csong@20 51 distanceToNearestBeat = min(abs(noteIndices - beatIndices[j]), abs(noteIndices - beatIndices[j+1]))/float(beatInterval)
csong@0 52
csong@1 53 # if this note is on-beat
csong@20 54 if distanceToNearestBeat == 0:
csong@1 55 measure = 0
csong@1 56 # or if this note is held on past the following beat, but ends on or before the later beat
csong@20 57 elif beatIndices[j+1] < nextNoteIndex <= beatIndices[j+2]:
csong@20 58 measure = float(2)/distanceToNearestBeat
csong@1 59 else:
csong@20 60 measure = float(1)/distanceToNearestBeat
csong@1 61 return measure
csong@0 62
csong@1 63 total = 0
csong@20 64 for i in range(len(noteIndices)):
csong@20 65 # if this is the last note, end_time is the index of the following note in the next bar
csong@20 66 if i == len(noteIndices)-1:
csong@20 67 # if the next bar is not none or a bar of full rest,
csong@20 68 # the nextNoteIndex is the sum of sequence length in the current bar and the noteIndex in the next bar
csong@20 69 if nextbarBinarySequence != None and nextbarBinarySequence != repeat([0],len(nextbarBinarySequence)):
csong@20 70 nextNoteIndex = get_note_indices(nextbarBinarySequence)[0]+sequenceLength
csong@20 71 # else when the next bar is none or full rest, end_time is the end of this sequence.
csong@20 72 else:
csong@20 73 nextNoteIndex = sequenceLength
csong@20 74 # else this is not the last note, the nextNoteIndex is the following element in the noteIndices list
csong@0 75 else:
csong@20 76 nextNoteIndex = noteIndices[i+1]
csong@20 77 # sum up the syncopation value for individual note at noteIndices[i]
csong@20 78 total += measure_pernote(noteIndices[i],nextNoteIndex)
csong@0 79
csong@2 80 #syncopation = float(total) / len(note_indices)
csong@0 81
csong@20 82 # return the total value, leave the normalisation done in the end
csong@2 83 return total