Mercurial > hg > syncopation-dataset
view Syncopation models/WNBD.py @ 2:031e2ccb1fb6
Added rhythm parser and parameter setter
author | Chunyang Song <csong@eecs.qmul.ac.uk> |
---|---|
date | Fri, 20 Mar 2015 18:28:08 +0000 |
parents | b2da092dc2e0 |
children | b959c2acb927 |
line wrap: on
line source
''' Author: Chunyang Song Institution: Centre for Digital Music, Queen Mary University of London ''' from BasicFuncs 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): syncopation = None num_beats = cumu_multiply(subdivision_seq[0:strong_beat_level+1]) # num_beats is the number of strong beats if len(seq)%num_beats != 0: print 'Error: the length of sequence is not subdivable by the subdivision factor in subdivision_seq.' else: # Find the indices of all the strong-beats beat_indices = [] beat_interval = len(seq)/num_beats for i in range(num_beats+1): beat_indices.append(i*beat_interval) if postbar_seq != None: # if there is a postbar_seq, add another two beats index for later calculation beat_indices += [len(seq)+beat_interval, len(seq)+ 2* beat_interval] note_indices = get_note_indices(seq) # all the notes # Calculate the WNBD measure for each note def measure_pernote(note_index, nextnote_index): # Find the nearest beats where this note locates - in [beat_indices[j], beat_indices[j+1]) j = 0 while note_index < beat_indices[j] or note_index >= beat_indices[j+1]: j = j + 1 # The distance of note to nearest beat normalised by the beat interval distance_nearest_beat = min(abs(note_index - beat_indices[j]), abs(note_index - beat_indices[j+1]))/float(beat_interval) # if this note is on-beat if distance_nearest_beat == 0: measure = 0 # or if this note is held on past the following beat, but ends on or before the later beat elif beat_indices[j+1] < nextnote_index <= beat_indices[j+2]: measure = float(2)/distance_nearest_beat else: measure = float(1)/distance_nearest_beat return measure total = 0 for i in range(len(note_indices)): if i == len(note_indices)-1:# if this is the last note, end_time is the index of the following note in the next bar if postbar_seq != None and postbar_seq != repeat([0],len(postbar_seq)): nextnote_index = get_note_indices(postbar_seq)[0]+len(seq) else: # or if the next bar is none or full rest, end_time is the end of this sequence. nextnote_index = len(seq) else: nextnote_index = note_indices[i+1] total += measure_pernote(note_indices[i],nextnote_index) #syncopation = float(total) / len(note_indices) return total