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